Instantiating Multiple Beans of the Same Class with Spring Annotations – 用Spring注解实例化同一类别的多个Bean

最后修改: 2022年 7月 8日

1. Overview


The Spring IoC container creates and manages Spring beans, which serve as the core of our application. Creating an instance of a bean is identical to creating objects from plain Java classes. However, generating several beans of the same class can be challenging.

Spring IoC 容器创建并管理 Spring Bean,它是我们应用程序的核心。创建Bean的实例与从普通的Java类中创建对象是相同的。然而,生成同一类别的多个Bean可能是一个挑战。

In this tutorial, we’ll learn how to use annotations in the Spring framework to create multiple beans of the same class.


2. Using Java Configuration


This is the simplest and easiest way to create multiple beans of the same class using annotations. In this approach, we’ll use a Java-based configuration class to configure multiple beans of the same class.


Let’s consider a simple example. We have a Person class that has two class members firstName and lastName:


public class Person {
    private String firstName;
    private String lastName;

    public Person(String firstName, String secondName) {
        this.firstName = firstName;
        this.lastName = secondName;

    public String toString() {
        return "Person [firstName=" + firstName + ", secondName=" + lastName + "]";

Next, we’ll construct a configuration class called PersonConfig and define multiple beans of the Person class inside it:


public class PersonConfig {
    public Person personOne() {
        return new Person("Harold", "Finch");

    public Person personTwo() {
        return new Person("John", "Reese");

Here, @Bean instantiates two beans with ids the same as the method names and registers them within the BeanFactory (Spring container) interface. Next, we can initialize the Spring container and request any of the beans from the Spring container.

在这里, @Bean实例化了两个id与方法名称相同的bean,并在BeanFactory(Spring容器)接口中注册了它们。接下来,我们可以初始化Spring容器并从Spring容器中请求任何一个Bean。

This strategy also makes it simple to achieve dependency injection. We can directly inject one bean, say personOne, into another bean of the same type, say personTwo using autowiring


The limitation of this approach is that we need to manually instantiate beans using the new keyword in a typical Java-based configuration style. 


Therefore, if the number of beans of the same class increases, we need to register them first and create beans in the configuration class. This makes it a more Java-specific approach, rather than a Spring-specific approach.


3. Using @Component Annotation


In this approach, we’ll use the @Component annotation to create multiple beans that inherit their properties from the Person class.


First, we’ll create multiple subclasses, namely PersonOne and PersonTwo, that extend the Person superclass:


public class PersonOne extends Person {

    public PersonOne() {
        super("Harold", "Finch");
public class PersonTwo extends Person {

    public PersonTwo() {
        super("John", "Reese");

Next, in the PersonConfig file, we’ll use the @ComponentScan annotation to enable component scanning throughout the entire package. This enables the Spring container to automatically create beans of any class annotated with @Component:


public class PersonConfig {


Now, we can just use the PersonOne or PersonTwo beans from the Spring container. Everywhere else, we can use the Person class bean.


The problem with this approach is that it doesn’t create multiple instances of the same class. Instead, it creates beans of classes that inherit properties from a superclass. Therefore, we can use this solution only in situations where the inherited class doesn’t have any additional properties defined. Moreover, the usage of inheritance increases the overall complexity of the code.


4. Using BeanFactoryPostProcessor


The third and final approach utilizes a custom implementation of the BeanFactoryPostProcessor interface for creating multiple bean instances of the same class. This can be achieved using the following steps:


  • Creating a custom bean class and configuring it using the FactoryBean interface
  • Instantiating multiple beans of the same type using BeanFactoryPostProcessor interface

4.1. Custom Bean Implementation 


To understand this approach better, we’ll extend the same example further. Suppose there’s a Human class that is dependent upon multiple instances of the Person class:


public class Human implements InitializingBean {

    private Person personOne;

    private Person personTwo;

    public void afterPropertiesSet() throws Exception {
        Assert.notNull(personOne, "Harold is alive!");
        Assert.notNull(personTwo, "John is alive!");

    /* Setter injection */
    public void setPersonOne(Person personOne) {
        this.personOne = personOne;

    public void setPersonTwo(Person personTwo) {
        this.personTwo = personTwo;

The InitializingBean interface invokes the afterPropertiesSet() method to check whether BeanFactory has set all the bean properties and satisfied other dependencies. Additionally, we’re injecting and initializing two Person class beans, personOne and personTwo, using setter injection.


Next, we’ll create a Person class that implements the FactoryBean interface. A FactoryBean acts as a factory for creating other beans within the IoC container.


This interface is intended to create more instances of the bean that implements it. In our case, it generates instances of the type Person class and configures it automatically:


@Qualifier(value = "personOne, personTwo")
public class Person implements FactoryBean<Object> {
    private String firstName;
    private String secondName;

    public Person() {
        // initialization code (optional)

    public Class<Person> getObjectType() {
        return Person.class;

    public Object getObject() throws Exception {
        return new Person();

    public boolean isSingleton() {
        return true;

    // code for getters & setters

The second important thing to notice here is the use of the @Qualifier annotation that contains names or bean ids of multiple Person types at the class level. There’s a reason behind using @Qualifier at the class level, in this case, which we’re going to see next.

这里需要注意的第二件重要的事情是 使用@Qualifier注解,该注解在类级别上包含多个Person类型的名称或bean ids。在这种情况下,在类级别上使用@Qualifier是有原因的,我们接下来会看到。

4.2. Custom BeanFactory Implementation


Now, we’ll use a custom implementation of the BeanFactoryPostProcessor interface. Any class that implements BeanFactoryPostProcessor is executed before any Spring bean gets created. This allows us to configure and manipulate the bean lifecycle. 

现在,我们将使用BeanFactoryPostProcessor接口的一个自定义实现。任何实现BeanFactoryPostProcessor的类都会在任何Spring Bean被创建之前被执行。这允许我们配置和操纵Bean生命周期。

The BeanFactoryPostProcessor scans all the classes annotated with @Qualifier. Furthermore, it extracts names (bean ids) from that annotation and manually creates instances of that class type with the specified names:

BeanFactoryPostProcessor扫描了所有用@Qualifier注释的类。此外,它还从该注解中提取名称(bean id),并以指定的名称手动创建该类类型的实例:

public class PersonFactoryPostProcessor implements BeanFactoryPostProcessor {

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String, Object> map = beanFactory.getBeansWithAnnotation(Qualifier.class);
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            createInstances(beanFactory, entry.getKey(), entry.getValue());

    private void createInstances(ConfigurableListableBeanFactory beanFactory, String beanName, Object bean) {
        Qualifier qualifier = bean.getClass().getAnnotation(Qualifier.class);
        for (String name : extractNames(qualifier)) {
            Object newBean = beanFactory.getBean(beanName);
            beanFactory.registerSingleton(name.trim(), newBean);

    private String[] extractNames(Qualifier qualifier) {
        return qualifier.value().split(",");

Here, the custom BeanFactoryPostProcessor implementation gets invoked once the Spring container is initialized.


Next, to keep things simple, here we’ll use a Java configuration class to initialize the custom as well as BeanFactory implementations:


public class PersonConfig {
    public PersonFactoryPostProcessor PersonFactoryPostProcessor() {
        return new PersonFactoryPostProcessor();

    public Person person() {
        return new Person();

    public Human human() {
        return new Human();

The limitation of this approach lies in its complexity. Moreover, it’s not encouraged to use since it’s not the natural way of configuring beans in a typical Spring application.


Despite the limitations, this approach is more Spring specific and serves the purpose of instantiating multiple beans of similar type using annotations.


5. Conclusion


In this article, we’ve learned about instantiating multiple beans of the same class using Spring annotations using three different approaches.


The first two approaches are simple and Java-specific ways to instantiate multiple Spring beans. However, the third one is a bit tricky and complex. But, it serves the purpose of bean creation using annotations.

前两种方法是简单的、针对Java的实例化多个Spring Bean的方法。然而,第三种方法有点棘手和复杂。但是,它可以达到使用注解创建Bean的目的。

As always, the source code for the examples is available over on GitHub.