Skip to content
Advertisement

What happens when we define bean with different names with Annotations and XML config?

The coach object is created with Annotations and coach2 is created with XML configuration file. They both refering to the tennisCoach class.

In singleton scope beans refer to the same place in memory but in this situation memory place is different.

I have two questions.

Why Spring lets us create two objects?

Why it doesn’t give an error about why an id is assigned to this object with annotation and we define the object again in XML or vice versa.

Does Spring create objects in prototype scope?

Coach coach = context.getBean("tennisCoach", Coach.class);
Coach coach2 = context.getBean("myCoach", Coach.class);
        
System.out.println(coach); //output: demo.TennisCoach@451001e5
System.out.println(coach2); //output: demo.TennisCoach@2b40ff9c

applicationContext.xml

<bean id="myCoach" class="demo.TennisCoach"></bean>

TennisCoach.java

@Component
public class TennisCoach implements Coach {...}

I know that one definition is enough for bean but I was just wondering about this situation.

Advertisement

Answer

Let me be more clear. Scope prototype creates a new bean every time you inject it. So if you have bean A and you inject it in bean B and C you will have two instance of bean A created.

Indeed let’s make some examples with singletons with xml and annotation. let’s say you have this xml configuration:

<bean id="myCoach1" class="demo.TennisCoach"></bean>
<bean id="myCoach2" class="demo.TennisCoach"></bean>
<bean id="bean1" class="demo.Bean1">
    <property name=“coach” ref=“myCoach1” />
</bean>
<bean id="bean2" class="demo.Bean2">
    <property name=“coach” ref=“myCoach2”/>
</bean>

So what’s happening here we are creating two beans of type demo.TennisCoach and injecting them by name in bean1 and bean2.

We can also use annotation configuration to achieve the same results:

@Configuration
public class Configuration {

    @Bean(name = “myCoach1”)
    public TennisCoach createMyCoach1()   {
        return new TennisCoach();
    }

    @Bean(name = “myCoach2”)
    public TennisCoach createMyCoach2()   {
        return new TennisCoach();
    }

    @Bean
    public Bean1 createBean1(@Qualifaer(“myCoach1” TennisCoach coach) {
        return new Bean1(coach);
    }

    @Bean
    public Bean2 createBean2(@Qualifaer(“myCoach2” TennisCoach coach) {
        return new Bean2(coach);
    }
}

Note the usage of @Qualifier to tell spring witch bean to inject. If you don’t use it spring doesn’t know which of the two TennisCoach should inject because by default it injects by type.

The same happens with @Autowired it by default injects by type but you can combine it with @Qualifier to inject the correct bean if you have more than one of the same type.

You can even mix xml and annotation (I don’t suggest it:

@Configuration
@ImportResource({“classpath:application-context.xml”})
public class Configuration {
    @Bean
    public Bean1 createBean1(@Qualifaer(“myCoach1” TennisCoach coach) {
        return new Bean1(coach);
    }

    @Bean
    public Bean2 createBean2(@Qualifaer(“myCoach2” TennisCoach coach) {
        return new Bean2(coach);
    }
    
}
Advertisement