歧义性的简单场景如下:
package noUniqueBeanDefinition;
public interface Dessert {
public void getDessert();
}
package noUniqueBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class Cake implements Dessert {
public void getDessert() {
System.out.println("=====Cake=====");
}
}
package noUniqueBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class Cookies implements Dessert {
public void getDessert() {
System.out.println("=====Cookies=====");
}
}
package noUniqueBeanDefinition;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component("iceCream")
public class IceCream implements Dessert {
public void getDessert() {
System.out.println("=====IceCream=====");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/aop/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="noUniqueBeanDefinition"/>
</beans>
package noUniqueBeanDefinition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("../ApplicationContextXml.xml")
public class DessertTest {
@Autowired
Dessert dessert;
@Test
public void test() {
dessert.getDessert();
}
}
当调用DessertTest类中的test()方法的时候,编译器不知道调用哪个bean,会报
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'noUniqueBeanDefinition.Dessert' available:
expected single matching bean but found 3: cake,cookies,iceCream
避免装配的歧义性的2中方案:
- 首选:使用@Primary
- 限定符:使用@Qualifier(“xxxx”)
首选
修改IceCream类如下
package noUniqueBeanDefinition;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component("iceCream")
@Primary
public class IceCream implements Dessert {
public void getDessert() {
System.out.println("=====IceCream=====");
}
}
在类名上加上@Primary,表示IceCream为首选。
再次调用DessertTest类中的test()方法的时候,返回
=====IceCream=====
如果这时候再在Cake类上加上@Primary,会报和上面一样的错。两个首选就等于没有首选。
所以首选的局限性就是只能设置一个,设置多个相当与没设置。
限定符—@Qualifier注解是使用限定符的主要方式。
修改DessertTest类如下:
package noUniqueBeanDefinition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("../ApplicationContextXml.xml")
public class DessertTest {
@Autowired
@Qualifier("iceCream")
Dessert dessert;
@Test
public void test() {
dessert.getDessert();
}
}
为@Qualifier注解所设置的参数就是想要注入的bean的ID。
缺点:@Qualifier注解所设置的参数与要注入的bean的名称是紧耦合。对类名称的任意改动都会导致限定符的失败。避免出现紧耦合的方式就是在类上加上@Qualifier(“xxxx”),这样在装配的时候就是装配xxxx,修改类名不会影响装配
例如:
package noUniqueBeanDefinition;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("iceCream")
@Qualifier("cream")
public class IceCream implements Dessert {
public void getDessert() {
System.out.println("=====IceCream=====");
}
}
package noUniqueBeanDefinition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("../ApplicationContextXml.xml")
public class DessertTest {
@Autowired
@Qualifier("cream")
Dessert dessert;
@Test
public void test() {
dessert.getDessert();
}
}
调用test()方法,返回=====IceCream=====