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.