當一個接口,有多個實現類且均已注入到spring容器中了,使用時@AutoWired是byType的,而這些實現類類型都相同,此時就需要使用@Qualifier明確指定使用那個實現類。因此,@Qualifier是byName的。
1、基本
public interface Formatter { String format(); } @Component("fooFormatter") public class FooFormatter implements Formatter { @Override public String format() { return "foo"; } } @Component("barFormatter") public class BarFormatter implements Formatter { @Override public String format() { return "bar"; } }
idea提示,必須添加@Qualifier,否則紅線。
最后,形如:
@SpringBootTest class QualifierTest { @Qualifier("barFormatter") @Autowired private Formatter formatter; @Test void test() { System.out.println(formatter.format()); } }
執行,輸出:bar
如果將barFormatter改成fooFormatter,輸出:foo。
2、對於實現類,可不用在@Compoment后的括號里聲明名稱,可以新增@Qualifier指定名稱,如:
@Component @Qualifier("fooFormatter") public class FooFormatter implements Formatter { 。。。 } @Component @Qualifier("barFormatter") public class BarFormatter implements Formatter { 。。。 }
3、對於實現類,去掉名稱,加上@Primary,也可以實現。意思是:默認使用@Primary的實現類,無需使用@Qualifier明確指定使用那個實現類了。
@Component @Primary public class FooFormatter implements Formatter { ... } @Component public class BarFormatter implements Formatter { ... }
但是,如果以上2個實現類都加上了@Primary,依賴時,就會報錯:
如果,@Qualifier與@Primary同時使用呢?優先使用@Qualifier指明的實現類。如:
@Qualifier("barFormatter") @Autowired private Formatter formatter;
輸出:bar。
@Primary一般在DataSource中用的較多,因為有druid實現、c3p0實現,而一般使用一個具體的連接池,因此為了偷懶,就采用@Primary了。
4、在多個實現類中,使用指定實現類的另外一種方法是,屬性名稱寫全了。
@Component public class FooFormatter implements Formatter { 。。。 } @Component public class BarFormatter implements Formatter { 。。。 } @SpringBootTest class QualifierTest { @Autowired private Formatter barFormatter; @Test void test() { System.out.println(barFormatter.format()); } }
輸出:bar