Annotations are used in Spring, often using @autowired, which is automatically injected based on Type Type by default. But there are special cases where there may be several different implementation classes for the same interface, and only one of them is used by default. Here is a simple use example.

There is the following interface

public interface Singer {
    String sing(String lyrics);
}
Copy the code

There are two implementation classes:

Public class MetalSinger implements Singer{@override public String sing(String lyrics) {return "I am singing with DIO voice: "+lyrics; }}Copy the code

// Note that there are no annotations here

public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics; }}Copy the code

And here’s what’s going to be injected into it

@Component
 public class SingerService {
        private static final Logger logger = LoggerFactory.getLogger(SingerService.class);
    @Autowired
    private Singer singer;
    public String sing() {return singer.sing("song lyrics"); }}Copy the code

I am singing with DIO voice: song lyrics. The reason for this is simply that OperaSinger does not have @copmonent or @service annotation on it, so when Spring does inject, it will find only MetalSinger. That’s why we have this result.

But if the OperaSinger class is annotated with @copmonent or @service, something interesting happens. You’ll find an error result or exception: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger

The tip is clear: Spring does not choose which one to inject based on type. That’s where @primay comes in.

@Primary
@Component
public class OperaSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics; }}Copy the code

If the code is changed to this and run again, the result is: “I am singing in Bocelli voice: song Lyrics”, using @primary to tell Spring which specific implementation to choose in case of hesitation.

Use the @qualifier annotation to solve the problem

Change the two classes above to the following:

@component // Annotate @qualifier ("metalSinger")
public class MetalSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}

@Component
@Qualifier("opreaSinger")
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics; }} @component public class SingerService {private static final Logger Logger = LoggerFactory.getLogger(SingerService.class); @Autowired private Singer singer; @Qualifier("opreaSinger")
    public String sing() {return singer.sing("song lyrics"); }}Copy the code