当一个接口,有多个实现类且均已注入到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