In last post we have seen how @Autowired
can be used at multiple places to inject the dependent beans. Spring framework handles the dependency between the components and based on field, setter or constructor injection injects appropriate objects.
Issue?
What happens when spring context has multiple beans of same type? which object spring framework injects for @Autowired
annotation?
If we have single bean of required type in the spring context, there is no ambiguity to framework and it will inject the dependent bean wherever required.
How Spring framework handle such scenarios?
When spring framework gets into situation of multiple beans of same type which need to be injected in one of the @Autowired
dependency, it will follow the three
steps to resolve the ambiguity.
By Default IoC container will always look for
class type
of bean to inject.
Step 1: look for bean name with same parameter/field name.
Spring IoC container will look for bean name with equal to parameter name mentioned with @Autowired
annotation in filed, setter parameter, constructor parameter.
// field injection
@Autowired
private SomeBean bean; // here spring looks for bean with name "bean" in context
// setter injection
@Autowired
public void setSomeBean(SomeBean bean1){ // here spring looks for bean with name "bean1" in context to inject.
this.bean = bean1;
}
// constructor injection
@Autowired
public Example(SomeBean bean2){ // here spring looks for bean with name "bean2" in context to inject.
this.bean=bean2;
}
if no matching name bean found, follow step 2
Step 2: Spring IoC container looks for bean marked as @Primary
bean
So if no matching name bean found, then spring IoC Container check for if there is any bean among multiple beans which is marked as @Primary
bean, if yes inject that bean.
@Primary // this is primary bean
@Bean
public SomeBean myBean(){
return new SomeBean("Hello");
}
@Bean // this is normal bean
public SomeBean myOtherBean(){
return new SomeBean("Welcome");
}
// when @Autowired is invoked, as we have multiple beans of same class type, @Primary bean will be injected for below wiring.
@Autowired
public SomeBean bean; // as no name bean matching with myBean, myOtherBean so Primary bean will be injected here.
If no
@Primary
bean found in context, follow step 3
Step 3: Spring IoC container will look for @Qualifier annotation and find the bean with name matching.
Now, IoC container checks if @Qualifier
is used or not and if found look for the name of the bean mentioned in @Qualifier
and injects that.
@Bean
public SomeBean myBean(){
return new SomeBean("Hello");
}
@Bean
public SomeBean myOtherBean(){
return new SomeBean("Welcome");
}
// when @Autowired is invoked, as we have multiple beans of same class type, @Primary bean not found checks name with @Qualifier and injects below
@Autowired // here qualifier used is "myBean" so IoC will inject the bean with name myBean
public Example(@Qualifier("myBean")SomeBean bean){
this.bean = bean;
}
Use of @Qualifier is beneficial as the parameter name can change based on developers choice to improve readability of code, but it will not impact the autowiring due to qualifier name used.
If all the above step followed and no matching bean is found then it will throw an exception NoUniqueBeanDefinitionException
as multiple beans are present but are ambiguious.
Top comments (0)