当我们需要一个bean,但是spring容器帮我们找到了两个或多个时怎么办?当希望从容器中获取到一个bean对象的时候,容器中却找到了多个匹配的bean,出现这样的情况时会出现什么问题又怎么解决?
1,出现的问题
来一个案例:
Service接口
public interface Service {
}
两个实现类
public class serviceImpl1 implements Service {
}
public class serviceImpl2 implements Service {
}
上面代码,定义了一个接口Service,创建了两个类serviceImpl1 ,serviceImpl2 都实现了Service接口。
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<bean id="impl1" class="com.chen.serviceImpl1"></bean>
<bean id="impl2" class="com.chen.serviceImpl2"></bean>
</beans>
定义impl1和impl2两个bean
测试输出:
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml");
Service bean = context.getBean(Service.class);
System.out.println(bean);
}
}
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.chen.Service' available: expected single matching bean but found 2: impl1,impl2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1273)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1174)
at com.chen.Main.main(Main.java:12)
可以看到输出错误,错误的原因是:spring容器中定义了2个bean,分别是impl1和impl2,这两个bean对象都实现了Service接口,而用例中我们想从容器中获取Service接口对应的bean,此时容器中有2个候选者(impl1和impl2)满足我们的需求,此时spring容器不知道如何选择,到底是返回impl1呢还是返回impl2呢?spring容器也不知道,所以报错了。
2,解决办法
上面的问题是当希望从容器中获取到一个bean对象的时候,容器中却找到了多个匹配的bean,此时spring不知道如何选择了,就会报这个异常。
spring中可以通过bean元素的primary属性来解决这个问题,可以通过这个属性来指定当前bean为主要候选者,当容器查询一个bean的时候,如果容器中有多个候选者匹配的时候,此时spring会返回主要的候选者。
我们把上面的bean.xml改成如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<bean id="impl1" class="com.chen.serviceImpl1" primary="true"></bean>
<bean id="impl2" class="com.chen.serviceImpl2"></bean>
</beans>
此时输出:
com.chen.serviceImpl1@73846619
可以看到正常输出了com.chen.serviceImpl1,因为com.chen.serviceImpl1置为主要候选者,spring就会将它返回。
总结:
- 当从容器中查找一个bean的时候,如果容器中出现多个Bean候选者时,可以通过primary=”true”将当前bean置为首选者,那么查找的时候就会返回主要的候选者,否则将抛出异常。
- 还有当候选者中如果有多个bean都将primary置为true,此时spring还是会不知道返回哪个的,也会报错,不知道如何选择了。