Understand the purpose of @Primary and @Autowried annotations in Spring Framework and when to use which annotation.
Context
While working with enterprise applications we usually create multiple beans of the same type and sometimes this can lead to problems wherein we get an error stating multiple beans of the same type are found and bean wiring cannot be performed in that case. This problem can be solved using @Primary and @Qualifier annotations that are available in Spring Framework.
These annotations basically provide instructions to the Spring container stating “during the bean wiring process, if multiple beans of the same type are found which one to consider in that case”.
@Primary Annotation
@Primary annotation should be used when we have multiple beans of the same type and during the bean wiring process, we want to give preference to a single bean that is marked with @Primary annotation.
@Qualifier Annotation
@Qualifier annotation should be used when we have multiple beans of the same type and during the bean wiring process, we want to wire a specific bean. Here we will explicitly specify which bean we are interested in.
Note: @Qualifier has higher priority than @Primary
Example
@Component
@Primary
class TwoWheeler implements Vehicle {}
@Component
class ThreeWheeler implements Vehicle {}
@Component
@Qualifier("FourWheelerQualifier")
class FourWheeler implements Vehicle {}
@Component
class Bike {
// Bean TwoWheeler will be autowired in this case
@Autowired
private Vehicle vehicle;
}
@Component
class Car {
// Bean FourWheeler will be autowired in this case
@Autowired
@Qualifier("FourWheelerQualifier")
private Vehicle vehicle;
}
JavaIn the above example, we have created three beans of type Vehicle and we have marked the TwoWheeler bean with @Primary annotation and the FourWheeler bean with @Qualifier annotation. @Component annotation is responsible for creating the bean for a particular class.
For wiring the Spring beans, we are making use of @Autowired annotation which will tell the Spring framework that we have some dependency, please find the required bean in the application context and inject it here.
In line 15, we are specifying the Spring Framework that we are interested in bean of type Vehicle but we have not specified exactly which bean we are interested in. Since we have multiple beans of type Vehicle, Spring Framework will give priority to the bean that is annotated with @Primary annotation, in this case, the TwoWheeler bean.
In line 23, we are specifying the Spring Framework that we are interested in bean of type Vehicle and we have also specified the exact bean we are interested in. In this case, Spring Framework will look for the exact bean that we have specified and it will wire the same i.e. it will wire the FourWheeler bean that is annotated with @Qualifier annotation.
Different Scenarios
- What will happen if we remove both the annotations i.e. @Primary and @Qualifier from the above example?
In this case, the application will fail to start because during the auto-wiring process, Spring Framework will find multiple beans of the same type and it will not be able to make a decision exactly which bean to inject in this case. - What will happen if we remove the @Qualifier(“FourWheelerQualifier”) annotation at line 23?
In this case, the TwoWheeler bean will be wired by Spring Framework because the TwoWheeler bean is marked with @Primary annotation due to which it will be given the preference during the wiring process. - How can we wire the ThreeWheeler bean at line 23?
We can replace the @Qualifier(“FourWheelerQualifier”) annotation with @Qualifier(“ThreeWheeler”). Even though we have not explicitly used @Qualified annotation while creating the ThreeWheeler bean, Spring Framework will internally create the bean with the name “ThreeWheeler”.
Add a Comment