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& ...
随机推荐
- Wiring in Spring: @Autowired, @Resource and @Inject 区别
refer:https://www.baeldung.com/spring-annotations-resource-inject-autowire 主要是查找顺序不一致: @Resource Mat ...
- linux上安装Docker (非常简单的安装方法) 2019
Docker的三大核心概念:镜像.容器.仓库 镜像:类似虚拟机的镜像.用俗话说就是安装文件. 容器:类似一个轻量级的沙箱,容器是从镜像创建应用运行实例, 可以将其启动.开始.停止.删除.而这些容器都是 ...
- centos7环境变量配置错误以至于命令不可使用
2021-07-16 问题: centos7在配置环境变量的时候少打了$,导致很多命令不能使用 解决方法: 在命令行输入: export PATH=/usr/local/sbin:/usr/local ...
- Java如何搭建脚手架(自动生成通用代码),创建自定义的archetype(项目模板)
.personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...
- Mybatis-plus<二>通用CRUD,分页
Mybatis-plus<二>通用CRUD,分页 与博客Mybatis-plus<一>为同一个Springboot项目. Demo GitHub下载地址:https://git ...
- WEB漏洞——RCE
RCE(remote command/code execute)远程命令/代码执行漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统. RCE漏洞 应用程序有时需要调用一 ...
- 源码编译安装 LNMP及论坛
一.安装Nginx服务 systemctl stop firewalld systemctl disable firewalld setenforce 0 1.安装依赖包 yum -y install ...
- android开发使用jxl创建Excel
这周水了几天,今天把博客赶上,找找状态. 周五的时候终于完成了课堂测试第二阶段,主要的难点就是生成Excel表并将填写的数据插入到Excel表中. 一.jxl使用 1.创建或读取一个工作薄 Workb ...
- 【PHP数据结构】图的概念和存储结构
随着学习的深入,我们的知识也在不断的扩展丰富.树结构有没有让大家蒙圈呢?相信我,学完图以后你就会觉得二叉树简直是简单得没法说了.其实我们说所的树,也是图的一种特殊形式. 图的概念 还记得我们学习树的第 ...
- PHP设计模式之门面模式
门面模式,也叫外观模式.不管是门面还是外观,都是我们对外的媒介,就好像我们的脸面一样.所以,这个模式最大的特点就是要表现的"好看".怎么说呢?一堆复杂的对象调用,自己都看蒙了,特别 ...