Spring依赖注入(3)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ymaini/article/details/82259245

介绍

本文主要介绍前文Spring依赖注入(2)的遗留问题

  • 自动装配Bean歧义问题

自动装配Bean歧义问题

Spring自动装配bean时, 必须确保bean的唯一、无歧义性, 否则Spring自动装配时无法确定具体应该装配的bean, 报出bean不唯一异常, org.springframework.beans.factory.NoUniqueBeanDefinitionException

示例描述

我们定义了一个向量运算的接口, 同时定义了向量求和和向量点乘的类实现该接口,两个类均使用@Component的注解, 在使用@Autowired注解加载向量运算时存在歧义导致加载失败。

  • 向量运算接口

    package com.notepad.springnote.inject;
    /**
    * Description: 2个向量之间的运算接口
    * <p>
    * Create:      2018/6/30 10:41
    *
    * @author Yang Meng([email protected])
    */
    public interface BaseVectorOperation {
      Double process(Double[] v1, Double[] v2) throws Exception;
    }
  • 向量求和

    package com.notepad.springnote.inject;
    import org.springframework.stereotype.Component;
    /**
    * Description: 向量求和
    * <p>
    * Create:      2018/6/30 10:49
    *
    * @author Yang Meng([email protected])
    */
    @Component
    public class VectorSum implements BaseVectorOperation {
    
      @Override
      public Double process(Double[] v1, Double[] v2) throws Exception {
          if (v1.length != v2.length) throw new AssertionError();
          double res = 0;
          for (int i = 0; i < v1.length; i++) {
              res += v1[i] + v2[i];
          }
          return res;
      }
    }
  • 向量点乘

    package com.notepad.springnote.inject;
    import org.springframework.stereotype.Component;
    /**
    * Description: 2个向量之间的点乘
    * <p>
    * Create:      2018/6/30 10:44
    *
    * @author Yang Meng([email protected])
    */
    @Component
    public class VectorDot implements BaseVectorOperation {
    
      @Override
      public Double process(Double[] v1, Double[] v2) throws Exception {
          if (v1.length != v2.length) throw new AssertionError();
          double res = 0.0;
          for (int i = 0; i < v1.length; i++) {
              res += v1[i] * v2[i];
          }
          return res;
      }
    }
  • 代码自测

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = InjectConfig.class)
    public class BaseVectorOperationTest {
    
    // 加载bean歧义
      @Autowired
      private BaseVectorOperation operation;
    
      @Test
      public void testProcess() throws Exception {
          Double[] v1 = {0.1, 0.2};
          Double[] v2 = {0.1, 0.3};
          assert v1.length == v2.length;
          System.out.println(operation.process(v1, v2));
      }
    }

解决方法

  • 定义bean时添加@Primary注解标记首选,当加载时优先选择加载注解的bean。示例如下:

    // 将向量点乘标记为首选bean, 在加载时出现BaseVectorOperation时优先选用向量点乘
    @Primary
    @Component
    public class VectorDot implements BaseVectorOperation {....}
  • 加载bean时添加@Qualifier注解限定装配的bean。如果没有指定限定符的bean将会给定一个默认的限定符(bean名称的基础上首字母小写, 例如:VectorDot的限定符为 vectorDot ),加载方法如下:

    @Autowired
    // 加载向量求和
    @Qualifier(value = "vectorSum")
    private BaseVectorOperation operation;
  • 定义bean时添加@Qualifier创建限定符: 针对解决方法2限定符和bean的名称是紧耦合的, 一旦改动容易出现错误, 为此通过自定义解决, 示例如下:

    // 为向量点乘自定义限定符, 后续的加载使用dot即可加载VectorDot
    @Qualifier("dot)
    @Component
    public class VectorDot implements BaseVectorOperation {....}

Github代码

https://github.com/yangbigmeng/notepad

参考

Spring In Action(第四版). 第三章

猜你喜欢

转载自blog.csdn.net/ymaini/article/details/82259245