The often overlooked annotation @Primary in spring

From: Annotation @Primary that is often overlooked in spring

Annotation is used in spring, often using @Autowired, which is automatically injected according to the type Type by default. But in some special cases, there may be several different implementation classes for the same interface, and the role of @Primary comes out when only one of them is adopted by default. Below is a simple usage example.

There is the following interface

public interface Singer {
    String sing(String lyrics);
}

There are the following two implementation classes:
@Component // Annotate to let spring recognize
public class MetalSinger implements Singer{

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

// 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;
    }
}
The following is injected into the above interface implementation class:
@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");
    }
}

What happens in the end?
I am singing with DIO voice: song lyrics. The reason is very simple, the class OperaSinger is not annotated with @Copmonent or @Service at all, so when spring injects it, only the implementation class MetalSinger can be found. That’s why this result is obtained.

But if once the OperaSinger class is annotated with @Copmonent or @Service, interesting things will happen, you will find a wrong 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, the operaSinger

prompt is very clear, spring cannot choose which one to inject according to the type. This is where @Primay can shine.
@Primary
@Component
public class OperaSinger implements Singer{


    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
If the code is changed to this and run again, the result is as follows:
"I am singing in Bocelli voice: song lyrics", using @Primary to tell spring which specific implementation to prefer when hesitating.

Thinking: It seems that there is another way: using qualifier names, it should be better.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324772502&siteId=291194637