Spring自动装配歧义性笔记
Spring自动装配歧义性笔记
如果系统中存在两个都实现了同一接口的类,Spring在进行@Autowired自动装配的时候,会选择哪一个?如下:
// 一下两个类均被标记为bean
@Component
public class CD implements Playable {
@Override
public void play() {
System.out.println("CD is playing...");
}
}
@Component
public class Video implements Playable {
@Override
public void play() {
System.out.println("Video is playing...");
}
}
//配置类仅打开自动扫描
@Configuration
@ComponentScan(basePackages = "zhen"
public class MyConfig {
}
//测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyConfig.class)
public class MyConfigTest {
@Autowired
Playable playable;
@Test
public void checkNULL() {
Assert.assertNotNull(playable);
}
}
此时再次运行测试类会发现,FAILD并且报错:
Unsatisfied dependency expressed through field 'playable'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'zhen.Playable' available: expected single matching bean but found 2: CD,video // 找到了两个都bean都能匹配
自动装配歧义性问题
上面的异常就是出现了歧义性。Spring为我们扫描了我们代码中的bean(这个部分是没有问题的),但是,在自动装配的过程中却由于歧义性而报错,并且,造成这样的歧义性还有由于Autowired这个注解仅仅按照类型进行装配——上面的CD与Video都实现了Playable接口,Autowired注解仅告诉Spring在测试类中的playable接受一个Playable类型的对象但是这里有两个bean:CD、video都是Playable类型的,所以Spring不知道。
为了解决这个问题,我们需要通过一定的手段来限定:
声明首选的bean
限定自动转配的bean
声明首选的bean
根据名字我们很容易理解,就是声明在有歧义性情况下,Spring到底选择哪一个bean来装配。方式就是在bean组件下添加@Primary注解,例如在原先的CD的@Component下加上首选注解,再次运行测试代码,PASS。但是,这种方式通常只在同类型bean较少的或者是系统简单的情况使用,而且还存在一个情况:假如目前有两位开发人员,在各自的环境编写bean,他们都希望自己的bean是Primary的,都加该注解,实际上还是会报错,因为系统现在同样有两个Primary bean,Spring还是不能判断选择哪一个bean注入。
限定自动装配的bean——@Qualifier注解
首先,我们可以通过在@Component中加入字符串来更明确的指定bean id而不是使用Spring的默认bean id策略。就像如下:
@Component("myCD")
public class CD implements Playable {
// ...
}
@Component("myVideo")
public class Video implements Playable {
// ...
}
当这样指定以后,我们在自动转配的地方,使用@Qualifier("指定id")来限定我们要注入的确定的bean:
...
@Autowired
@Qualifier("myCD")
Playable playable;
...
再次运行不会报错。
关于@Qualifier,最佳的情形应该是来标记bean特性。但是,如果多个bean都有相同的特性,都是用了相同的标记的@Qualifier注解,那么同样又会出现歧义性问题。所以我们又要添加新的@Qualifier注解来进一步限定,这样做没有问题,但是Java语法规定,不允许在同一条目上重复出现相同类型的多个注解。你不能这么做:
// 编译器会报错
@Qualifier("myCD")
@Qaulifier("JayChou")
public class CD implements Playable {
...
}
为了结局这样的问题,我们可以创建自己的注解:
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.METHOD}) //字段注解
@Retention(RetentionPolicy.RUNTIME) //在运行期保留注解信息
@Qualifier // 需要使用@Qualifier注解来限定
public @interface MyCD {
}
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface JayChou {
}
如此定义了注解以后,我们就可以在原先的@Component下如下定义:
@Component
@MyCD
@JayChou
public class CD implements Playable {
...
}
并且在测试类下如下声明:
@Autowired
@MyCD
@JayChou
Playable playable;
测试通过!
Spring自动装配歧义性笔记的更多相关文章
- Spring自动装配(二)
为什么Spring要支持Autowire(自动装配) 先写几个类,首先定义一个Animal接口表示动物: 1 public interface Animal { 2 3 public void eat ...
- Spring 自动装配 Bean
Spring3系列8- Spring 自动装配 Bean 1. Auto-Wiring ‘no’ 2. Auto-Wiring ‘byName’ 3. Auto-Wiri ...
- spring 自动装配 default-autowire="byName/byType"
<PRE class=html name="code">spring 自动装配 default-autowire="byName/byType" ...
- Spring自动装配Bean详解
1. Auto-Wiring ‘no’ 2. Auto-Wiring ‘byName’ 3. Auto-Wiring ‘byType 4. Auto-Wirin ...
- Spring自动装配----注解装配----Spring自带的@Autowired注解
Spring自动装配----注解装配----Spring自带的@Autowired注解 父类 package cn.ychx; public interface Person { public voi ...
- Spring系列七:Spring 自动装配
相思相见知何日?此时此夜难为情. 概述 在Spring框架中,在配置文件中声明bean的依赖关系是一个很好的做法,因为Spring容器能够自动装配协作bean之间的关系.这称为spring自动装配. ...
- 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring自动装配Bean
除了使用 XML 和 Annotation 的方式装配 Bean 以外,还有一种常用的装配方式——自动装配.自动装配就是指 Spring 容器可以自动装配(autowire)相互协作的 Bean 之间 ...
- spring自动装配和通过java实现装配
1.组建扫描 在类上添加注解@Component注解可以实现组建扫描 @Component public class A{ ... } 2.自动装配 通过在属性上或者方法上添加@Autowired注解 ...
- 【spring 注解驱动开发】spring自动装配
尚学堂spring 注解驱动开发学习笔记之 - 自动装配 自动装配 1.自动装配-@Autowired&@Qualifier&@Primary 2.自动装配-@Resource& ...
随机推荐
- 我对数据库事务的理解(MYSQL中)
-- 设置数据库事务为手动的提交SET @@AUTOCOMMIT = 0;-- 查看是否被修改SELECT @@autocommit;-- 查看当前的编码格式SELECT @@character_se ...
- Java程序设计学习笔记(五) — 多线程
时间:2016-4-15 09:56 --多线程(还有多核编程) 1.进程 进程是一个正在执行中的程序. 每一个进程执行都有一个执行顺序,该顺序是一个执行路径, ...
- python操作图片
时间:2018-11-30 记录:byzqy 标题:python实现图片操作 地址:https://blog.csdn.net/baidu_34045013/article/details/79187 ...
- 字符型:char
字符型:char 字符变量的定义和输出 字符变量用于存储一个单一字符,在C语言中用char表示,其中每个字符变量都会占用1个字节.在给字符型变量赋值时,需要用一对因为半角格式的单引号(' ')把字 ...
- 图解最长回文子串「Manacher 算法」,基础思路感性上的解析
问题描述: 给你一个字符串 s,找到 s 中最长的回文子串. 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 「Ma ...
- vue 微信二维码扫码登录,附加 自定义样式
大概流程: 先安装 微信 的登录, 然后 局部引入,局部注册,方法调用,存 token,跳转路由 npm 安装 npm install vue-wxlogin --save-dev 微信安装 微信 ...
- vue element-ui 组件上传图片 以及对 图片的 宽高 和 大小 格式等 做出限制
vue 文件: 自行引用 elemen-ui <el-upload action=" 让后端给你上传地址 " ...
- Linux下chkconfig
1.chkconfig命令用于检查,设置系统的各种服务! 2.chkconfig语法 chkconfig [--add] [--del] [--list] [系统服务] 或 chkconfig [-- ...
- js判断是在移动端还是在pc端
function chatQQ3(){ if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { //移动端打开 ...
- 添加class和删除class以及判断是否含有class
addClass(document.body, 'showRightPanel') removeClass(document.body, 'showRightPanel') /** * Add ...