1. Introduction
In this tutorial, we’ll discuss what is the use of @Qualifier
annotation and which problem it solves. In this tutorial we’ll also discuss how @Qualifier
is different from @Primary
annotation.
2. What problem does @Qualifier solve?
While autowiring beans, Spring by default searches by types and does the bean injection. However, Spring may find it difficult when two or more beans qualifyfor injection as they are of the same type. When two or more beans qualify the search, Spring may not decide which bean should it inject. Let us see this with an example. In this example, we are trying to autowire a Printable
service in a Controller. Two services FilePrinter
and ScreenPrinter
are eligible for autowiring as both are Printable
.
@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"); } }
When you start the application you’ll get the error similar to this:
*************************** APPLICATION FAILED TO START *************************** Description: Field printer in com.learnitweb.demo.controller.HelloController required a single bean, but 2 were found: - filePrinter: defined in file [D:\sts-workspace\demo\target\classes\com\learnitweb\demo\ServiceImpl\FilePrinter.class] - screenPrinter: defined in file [D:\sts-workspace\demo\target\classes\com\learnitweb\demo\ServiceImpl\ScreenPrinter.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
As you can see in the error, to solve this issue there are two options, using @Primary
and @Qualifier
.
3. @Qualifier annotation
By using the @Qualifier
annotation, we can specify which bean needs to be injected. Lets work on our previous example to make it work using @Qualifier
.
@RestController public class HelloController { @Autowired @Qualifier("filePrinter") Printable printer; @GetMapping("/print") public void print() { printer.print(); } }
Notice the use of @Qualifier("filePrinter")
. Using @Qualifier
, we are specifying that we want a FilePrinter
to be used. This will help Spring to avoid the ambiguity. Note that the name provided in @Qualifier
annotation is name provided while implementing Printable
like @Service("filePrinter")
.
@Qualifier
may also be used to annotate other annotations that can then in turn be used as qualifiers. So @Qualifier
can be applied to the implementor of Printable
to achieve the same result.
@Service @Qualifier("filePrinter") public class FilePrinter implements Printable { @Override public void print() { System.out.println("file printer"); } }
@Service @Qualifier("screenPrinter") public class ScreenPrinter implements Printable { @Override public void print() { System.out.println("Screen Printer"); } }
4. @Primary annotation
Using @Primary
annotation is another way of solving ambiguity when more that one beans are eligible for autowiring.
@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
, this bean is used for autowiring. In our example, there are two Printable
, FilePrinter
and ScreenPrinter
. Since more than one bean is eligible to be autowired, you can annotate one with @Primary
to tell spring that this bean should be given preference in case of ambiguity.
@Service @Primary public class ScreenPrinter implements Printable { @Override public void print() { System.out.println("Screen Printer"); } }
In this example, ScreenPrinter
will be used in case of ambiguity.
If both the
@Qualifier
and@Primary
annotations are present, then the@Qualifier
annotation will have precedence.