Learnitweb

Spring @Primary annotation

1. Introduction

In this quick tutorial, we’ll discuss Spring’s @Primary annotation.

The @Primary annotation indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If there is exactly one bean annotated with @Primary among the candidates, it will be used for autowiring.

This annotation may be used on any class directly or indirectly annotated with @Component or on methods annotated with @Bean. Since @Repository, @Service and @Controller serve as specialization of @Component, it can be used with these annotations.

2. What problem does @Primary solve?

While autowiring beans, it is possible that there are more than one eligible candidates. While autowiring beans, Spring by default searches by types and does the bean injection. There will be ambiguity when two or more beans are registered of the same type. Let’s understand this with an example.

@RestController
public class HelloController {

  @Autowired
  Printable printer;

  @GetMapping("/print")
  public void print() {
    printer.print();
  }
} 
// imports omitted for brevity

@Service("filePrinter")
public class FilePrinter implements Printable {

  @Override
  public void print() {
    System.out.println("file printer");
  }
}
// imports omitted for brevity

@Service("screenPrinter")
public class ScreenPrinter implements Printable {

  @Override
  public void print() {
    System.out.println("Screen Printer");
  }
}

Spring throws NoUniqueBeanDefinitionException if we try to run the application with autowiring two or more beans of same type. In Spring Boot application the exception looks like this:

Field printer in com.learnitweb.demo.controller.HelloController required a single bean, but 2 were found

3. @Primary annotation

Lets see how the @Primary annotation solves the issue in our example.

@Service("screenPrinter")
@Primary
public class ScreenPrinter implements Printable {

  @Override
  public void print() {
    System.out.println("Screen Printer");
  }
}

Using @Primary annotation will let the Spring to know that ScreenPrinter should be given preference in case of ambiguity. Since two Printable beans are candidates for autowiring, ScreenPrinter will be given preference and will be used for autowiring.

4. Use @Primary With @Bean

The @Primary annotation can be used with @Bean to define the bean as ‘primary’ in case of ambiguity.

@Configuration
public class Config {

    @Bean
    public Printable ScreenPrinter() {
        return new ScreenPrinter();
    }

    @Bean
    @Primary
    public Printable FilePrinter() {
        return new FilePrinter();
    }
}

In this example, FilePrinter is given preference and used in case of ambiguity.