Issue
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.
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.
Solution
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);
}
}
Answered By - Pp88
Answer Checked By - Willingham (JavaFixing Volunteer)