处理自动装配的歧义性
仅有一个 bean 匹配所需的结果时,自动装配才是有效的。如果不仅有一个 bean 能够匹配结果的话,这种歧义性 Spring 自动装配。
例如下面案例
实体类
@Component public class IceCream implements Dessert { @Override public void show() { System.out.println("获得冰淇淋"); } }
@Component public class Cake implements Dessert { @Override public void show() { System.out.println("获得蛋糕"); } }
业务类
@Component public class MyService { private Dessert dessert; public void show(){ dessert.show(); } @Autowired public void setDessert(Dessert dessert) { this.dessert = dessert; } }
测试
public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(com.lt.ltconfig.class); MyService myService = (MyService) context.getBean("myService"); myService.show(); }
在这里,业务类根据接口匹配相应的 bean,但是继承了这个接口的 bean 有两个,Spring 不会帮我们选择,直接报错:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.lt.pojo.Dessert' available: expected single matching bean but found 2: cake,iceCream
此时,自动装配产生了歧义性。
要消除歧义性,Spring 提供了多种可选方案来解决这样的问题。可以将可选 bean 中的莫一个设为首选 (primary) 的 bean,或者使用限定符 (qualifier) 来帮助 Spring 将可选的 bean 的范围缩小到只有一个 bean。
1. 标识首选的 bean
通过将其中一个可选的 bean 设置为首选 (primary) bean 能够避免自动装配时的歧义性。当遇到歧义的时候,Spring 将会使用首选的 bean,而不是其他可选的 bean。当然,首选 bean 应该在一类 bean 中最多存在一个。设置首选 bean 的方法也很简单,在自动装配或者 java 配置中声明 @Primary 即可。xml 中将 bean 元素的 primary 属性设置为 true 即可。
2. 限定自动装配的 bean
2.1 使用限定符
@Qualifier 注解是使用限定符的主要方式,它可以与 @Autowired 和 @Inject 协同使用,在注入的时候指定想要注入进去的是哪个 bean。例如:
实体类
@Component @Qualifier("iceCream") public class IceCream implements Dessert { @Override public void show() { System.out.println("获得冰淇淋"); } }
业务类
@Component public class MyService { private Dessert dessert; public void show(){ dessert.show(); } @Autowired @Qualifier("iceCream") public void setDessert(Dessert dessert) { this.dessert = dessert; } }
当通过 Java 配置显示定义 bean 的时候,@Qualifier 也可以与 @Bean 注解一起使用:
@Bean @Qualifier("iceCream") public Dessert iceCream(){ return new IceCream(); }
2.2 使用自定义的限定符注解
实体类
@Component @Soft public class Cake implements Dessert { @Override public void show() { System.out.println("获得蛋糕"); } }
业务类
@Autowired @Soft public void setDessert(Dessert dessert) { this.dessert = dessert; }
自定义注解
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD, ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Soft { }
来源:https://www.cnblogs.com/miou/p/12256143.html