Spring

Spring @Primary Annotation

Introduction:

Spring @Primary annotation is used to give a higher preference to the marked bean when multiple beans of the same type exist.

Spring, by default, auto-wires by type. And so, when Spring attempts to autowire and there are multiple beans of the same type, we’ll get a NoUniqueBeanDefinitionException:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException
  : No qualifying bean of type [com.programmergirl.Person]
  is defined: expected single matching bean but found 2: student, teacher
...

To solve this, we can choose to use Spring @Primary annotation, thereby marking one bean to be the primary one.

In this tutorial, we’ll explore the usage of this annotation in more detail.

@Primary In Configuration Class:

Let’s say we have the following configuration class:

@Configuration
public class UniversityConfig {

    @Bean
    @Primary
    public Person student() {
        return new Student();
    }

    @Bean
    public Person teacher() {
        return new Teacher();
    }
}

Both Teacher and Student beans inherit from Person and so we have marked it as the return type of both of our @Bean annotated method.

However, please note that we have marked the Student bean to be the primary one using @Primary annotation. Now, let’s start up our application:

AnnotationConfigApplicationContext context =
  AnnotationConfigApplicationContext(UniversityConfig.class);

Person student = context.getBean(Person.class);
System.out.println(student.getClass());

We’ll see that a Student object got a preference while Spring attempted autowiring.

Spring Component With @Primary:

Let’s say we instead have our component scan enabled:

@Configuration
@ComponentScan(basePackages="com.programmergirl.beans")
public class UniversityConfig {   
}

For such cases, we can directly annotate our Spring component class with @Primary:

@Primary
@Component
public class Student implements Person {
    ...
}

@Component
public class Teacher implements Person {
   ...
}

Now, when directly trying to inject a Person type without a @Qualifier, a Student bean will get injected:

@Service
public class StudentService {

    // Student bean is primary and so it'll get injected
    @Autowired
    private Person student;

    public void printStudentDetails() {
        System.out.println(student.getClass());
        ...
    }
}

Conclusion:

In this quick tutorial, we explored the usages of @Primary annotation in Spring.

As the name suggests, we can use @Primary annotation to define a primary one when having multiple beans of the same type.

Be the First to comment.

Leave a Comment

Your email address will not be published. Required fields are marked *