Spring @Primary Annotation Example
November 11, 2021
This page will walk through Spring @Primary
annotation example.
1. The
@Primary
annotation is used to make a bean preferable when multiple beans are qualified to autowire a single-valued dependency.
2. When there is more than one bean for dependency injection, we see the error as “expected single matching bean but found n”. Such type of error can be avoided just by using
@Primary
annotation at any preferable bean.
3. The
@Primary
annotation is used with @Bean
, @Component
and @Service
annotations.
4. The
@Primary
annotation is equivalent to <bean>
element's primary
attribute in XML configuration.
5. The
@Primary
annotation is introduced in Spring 3.0.
Using @Primary with @Component
Here we have an interface and its two implementation classes.Animal.java
package com.concretepage; public interface Animal { void displayName(); }
package com.concretepage; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component @Primary public class Lion implements Animal { @Override public void displayName() { System.out.println("--- Lion ---"); } }
package com.concretepage; import org.springframework.stereotype.Component; @Component public class Tiger implements Animal { @Override public void displayName() { System.out.println("-- Tiger ---"); } }
@Primary
annotation has been marked with @Component
at Lion
class.
Now create a service to autowire the
Animal
object.
AnimalService.java
package com.concretepage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class AnimalService { private Animal animal; public Animal getAnimal() { return animal; } @Autowired public void setAnimal(Animal animal) { this.animal = animal; } }
Lion
and Tiger
beans are qualified to autowire for animal
parameter. But the Lion
will be injected because it is annotated with @Primary
annotation at class level.
AppConfig.java
package com.concretepage; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages="com.concretepage") public class AppConfig { }
package com.concretepage; import java.sql.SQLException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class SpringDemo { public static void main(String[] args) throws SQLException { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.refresh(); Animal animal = ctx.getBean(Animal.class); animal.displayName(); ctx.registerShutdownHook(); } }
Case 1. As we have used
@Primary
annotation on Lion
bean. This will be selected for dependency injection. Find the output.
--- Lion ---
@Primary
annotation on any bean, we will get error.
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.concretepage.Animal] is defined: expected single matching bean but found 2: lion,tiger at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
@Primary
annotation on both the beans, we will get error.
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.concretepage.Animal] is defined: more than one 'primary' bean found among candidates: [lion, tiger] at org.springframework.beans.factory.support.DefaultListableBeanFactory.determinePrimaryCandidate(DefaultListableBeanFactory.java:1183)
Using @Primary with @Bean
Find the code to use@Primary
annotation with @Bean
.
AppConfig.java
@Configuration public class AppConfig { @Primary @Bean public Animal lion() { return new Lion(); } @Bean public Animal tiger() { return new Tiger(); } }