笔记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>结果

 

posted @ 2018-04-18 10:43  雨落忧伤-  阅读(169)  评论(0编辑  收藏  举报