笔记4 解决自动装配时的歧义性
笔记4 解决自动装配时的歧义性
当多个bean实现同一接口时,如何装配指定的bean?
1.定义Dessert接口:Dessert.java
1 package Desserts; 2 3 public interface Dessert { 4 public void alert(); 5 6 }
2.创建三个实现Dessert接口的类:Cookies.java、IceCream.java、Cake.java,并分别添加@Component注解,表明是一个bean。
Cookies.java
1 package Desserts; 2 3 import org.springframework.stereotype.Component; 4 5 @Component() 6 public class Cookies implements Dessert { 7 8 @Override 9 public void alert() { 10 // TODO Auto-generated method stub 11 System.out.println("我是Cold、Creamy的Cookies!"); 12 } 13 14 }
IceCream.java
1 package Desserts; 2 3 import org.springframework.stereotype.Component; 4 5 @Component 6 public class IceCream implements Dessert { 7 8 @Override 9 public void alert() { 10 // TODO Auto-generated method stub 11 System.out.println("我是Cold、Soft的IceCream!"); 12 } 13 14 }
Cake.java
1 package Desserts; 2 3 import org.springframework.stereotype.Component; 4 5 @Component 6 public class Cake implements Dessert { 7 8 @Override 9 public void alert() { 10 // TODO Auto-generated method stub 11 System.out.println("我是Cake!"); 12 } 13 14 }
3.创建Java配置文件(自动化装配)。
DessertConfig.java
1 package Desserts; 2 3 import org.springframework.context.annotation.ComponentScan; 4 import org.springframework.context.annotation.Configuration; 5 6 @Configuration 7 @ComponentScan 8 public class DessertConfig { 9 10 }
4.测试
DessertTest.java
1 package Desserts; 2 3 import org.junit.Test; 4 import org.junit.runner.RunWith; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.test.context.ContextConfiguration; 7 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 9 @RunWith(SpringJUnit4ClassRunner.class) 10 @ContextConfiguration(classes = Desserts.DessertConfig.class) 11 public class DessertTest { 12 @Autowired 13 private Dessert d; 14 15 @Test 16 public void test() { 17 d.alert(); 18 19 } 20 21 }
5.结果分析
由于有三个Dessert接口的实现,所以在加载的时候就出现错误:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [Desserts.Dessert] is defined: expected single matching bean but found 3: cake,cookies,iceCream
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1079)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:967)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:543)
... 28 more
6.进行限定
方法一:
在使用@Component注解时直接指定bean的ID(或者使用@Qualifier来指定),在测试时用@Qualifier注解进行指定装配。
<1>在Cake.java中进行指定
1 package Desserts; 2 3 import org.springframework.stereotype.Component; 4 //@Qualifier("Cake") 5 @Component("Cake") 6 public class Cake implements Dessert { 7 8 @Override 9 public void alert() { 10 // TODO Auto-generated method stub 11 System.out.println("我是Cake!"); 12 } 13 14 }
<2>测试
package Desserts; 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(classes = Desserts.DessertConfig.class) public class DessertTest { @Autowired @Qualifier("Cake") private Dessert d; @Test public void test() { d.alert(); } }
<3>结果:
方法二:
使用@Primary注解进行标识,表明此bean的重要性,首先加载。
<1>在IceCream.java中进行指定
1 package Desserts; 2 3 import org.springframework.context.annotation.Primary; 4 import org.springframework.stereotype.Component; 5 6 @Component 7 @Primary 8 public class IceCream implements Dessert { 9 10 @Override 11 public void alert() { 12 // TODO Auto-generated method stub 13 System.out.println("我是IceCream!"); 14 } 15 16 }
<2>测试
1 package Desserts; 2 3 import org.junit.Test; 4 import org.junit.runner.RunWith; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.test.context.ContextConfiguration; 7 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 9 @RunWith(SpringJUnit4ClassRunner.class) 10 @ContextConfiguration(classes = Desserts.DessertConfig.class) 11 public class DessertTest { 12 @Autowired 13 private Dessert d; 14 15 @Test 16 public void test() { 17 d.alert(); 18 19 } 20 21 }
<3>结果
方法三:
使用自定义的限定符进行注释。
当实现类既具有相同的特征、又有不同的特征时,这时就需要自定义限定符进行注释,因为Java不允许在同一个条目上重复出现相同类型 的多个注解。
<1>创建自定义注解
假设描述Dessert有三个关键字:Cold、Creamy、Soft,分别创建三个注解,只是类名不一样,在此给出Cold的代码。
Cold.java
1 package Desserts; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 import org.springframework.beans.factory.annotation.Qualifier; 9 10 @Target({ ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE }) 11 @Retention(RetentionPolicy.RUNTIME) 12 @Qualifier 13 public @interface Cold { 14 15 }
<2>对不同的类进行注解
IceCream.java
1 package Desserts; 2 3 import org.springframework.context.annotation.Primary; 4 import org.springframework.stereotype.Component; 5 6 @Component 7 @Primary 8 @Cold 9 @Soft 10 public class IceCream implements Dessert { 11 12 @Override 13 public void alert() { 14 // TODO Auto-generated method stub 15 System.out.println("我是Cold、Soft的IceCream!"); 16 } 17 18 }
Cookies.java
1 package Desserts; 2 3 import org.springframework.stereotype.Component; 4 5 @Component 6 @Cold 7 @Creamy 8 public class Cookies implements Dessert { 9 10 @Override 11 public void alert() { 12 // TODO Auto-generated method stub 13 System.out.println("我是Cold、Creamy的Cookies!"); 14 } 15 16 }
<3>测试
1 package Desserts; 2 3 import org.junit.Test; 4 import org.junit.runner.RunWith; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.test.context.ContextConfiguration; 7 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 9 @RunWith(SpringJUnit4ClassRunner.class) 10 @ContextConfiguration(classes = Desserts.DessertConfig.class) 11 public class DessertTest { 12 @Autowired 13 @Cold 14 @Creamy 15 private Dessert d; 16 17 @Autowired 18 @Cold 19 @Soft 20 private Dessert d2; 21 22 @Test 23 public void test() { 24 d.alert(); 25 d2.alert(); 26 27 } 28 29 }
<4>结果