@Autowired 和  @Qualifier

使用xml 注入的时候, 我们可以指定 autowire=“byType” 或“byName” 。

但是使用 注解的时候, @Autowired  只有一个 required 属性, 无法设置  by name或者 by type。 那么 这个时候, 我们可以使用 @Qualifier

@Autowired  @Qualifier 需要一起使用,他们是一个奇怪的组合, 组合到一起的时候, 表示,先尝试 by type, 出现冲突了,那么by name。 换句话说, 如果需要注入的某个类型的bean ,只有一个实例, 对应  @Autowired  @Qualifier  组合, 其中@Qualifier 可有可无, 有的话, 其 value 可以随便写。但是 如果有多个, 那就不一样的: 此时,@Qualifier也必须正确。

关于 @Bean

spring 在解析到 @Bean 的时候, 会自动给 参数中的 对象类型 注入 一个实例, 默认byType , 不需要 @Autowired 或者 @Qualifier

    @Bean
public LkCar datasource(LkBean lkBean) {
System.out.println("config datasrouce.");
return new LkCar(lkBean);
} @Bean
public LkBean aa() {
System.out.println("config bean aa");
LkBean bean = new LkBean();
bean.setStr("aa");
return bean;
} @Bean("bb")
// @Primary
public LkBean aabb() {
System.out.println("config bean bb");
LkBean bean = new LkBean();
bean.setStr("bb");
return bean;
}

java config 默认是使用 byType注册。 上面的代码中, 有两个类型为 LkBean的实例, 故实例化 LkCar的时候出错:

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'datasource' defined in com.anno.LkAnno: Unsatisfied dependency expressed through method 'datasource' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.anno.LkBean' available: expected single matching bean but found 2: aa,bb
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1134)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1028)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at AnnoIo22CTest.main(AnnoIo22CTest.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.anno.LkBean' available: expected single matching bean but found 2: aa,bb
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:172)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1114)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 19 more

解决方法有两个,

1 在其中一个参数bean 的方法上面添加 @Primary , 表明它是首选

2 把 datasource 签名改为:

public LkCar datasource(@Qualifier("bb")LkBean lkBean) {
...

这里的 @Autowired  是不需要的。 @Qualifier 必须放到 方法的参数中去, 而不是在 方法之上。

另外, 当一个类中有两个@Bean , 比如一个 为方法aa, 另一个返回值相同,但是@Bean("aa"), 那么, 前面的生效, 后面的无法注册为 spring 的bean, 因为已经注册过了一次了!

另外, 当我们有多个配置类的时候,  它们是会合并的,合并的规则是:

如果没有同名bean ,当然就简单的组合到一起就行了。

如果有冲突呢?  后面出现的覆盖前面的!!  这和 在一个 java config 中出现冲突的处理 顺序是相反的!!

另外, 我发现, 当我 @Autowire 一个 方法的时候, 如果在当前类有多个可选同类型 bean 实例,那么 会出错, 但是如果其他的 java config 配置类 还有一个 可选的同类型bean 实例, 那么就不会出错。

真是奇了怪了。  究其原因, 应该是 跟 bean 实例化的顺序有关, 如果 在Autowire 一个 方法的时候, 能够找到一个实例, 而不是多个, 那么久使用它。 否则如果发现多个, 那么久不行。!!

注意: @Bean 或者  java config 仅仅是定义及 注册了 bean 的定义,  真正的实例化是 在第一次使用它的时候(如果有冲突, 是这个时候才会发现)。

spring 之 注入之 by name or by type, or both ?的更多相关文章

  1. Spring自动注入properties文件

    实现spring 自动注入属性文件中的key-value. 1.在applicationContext.xml配置文件中,引入<util />命名空间. xmlns:util=" ...

  2. spring 属性注入

    Spring的核心技术室依赖注入,下面是依赖注入之属性注入的实现过程,牛刀小试,请看效果. 1.首先添加Spring.Web引用.本例中是使用分层思想来演示的,下面是项目的结构和UserModel类的 ...

  3. spring 多线程 注入 服务层 问题

    在用多线程的时候,里面要用到Spring注入服务层,或者是逻辑层的时候,一般是注入不进去的.具体原因应该是线程启动时没有用到Spring实例不池.所以注入的变量值都为null. 详细:http://h ...

  4. Spring 依赖注入方式详解

    平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...

  5. Spring的注入问题

    作下笔记,Spring的注入问题[多个实例问题] 解决方案如下: package student.life.support.platform.service.impl; import javax.an ...

  6. Spring依赖注入(IOC)那些事

    小菜使用Spring有几个月了,但是对于它的内部原理,却是一头雾水,这次借着工作中遇到的一个小问题,来总结一下Spring. Spring依赖注入的思想,就是把对象交由Spring容器管理,使用者只需 ...

  7. Spring依赖注入三种方式详解

    在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...

  8. Spring依赖注入:注解注入总结

    更多11   spring   依赖注入   注解   java 注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.S ...

  9. Spring 依赖注入,在Main方法中取得Spring控制的实例

    Spring依赖注入机制,在Main方法中通过读取配置文件,获取Spring注入的bean实例.这种应用在实训的时候,老师曾经说过这种方法,而且学Spring入门的时候都会先学会使用如何在普通的jav ...

随机推荐

  1. python 文件读写时用open还是codecs.open

    当我面有数据需要保存时,第一时间一般会想到写到一个txt文件中,当然,数据量比较大的时候还是写到数据库比较方便管理,需要进行网络传输时要序列化,json化.下面主要整理一下平时用的最多的写入到文件中, ...

  2. js获取table中的列的数字的和

    function getTdValue(a) { var tableId = document.getElementById("tab"); var num; for(var i= ...

  3. Windows10 bypassUAC绕过用户账户控制

    使用这个github上的项目: https://github.com/L3cr0f/DccwBypassUAC 可以自行编译 全程UAC不介入,没反应. 测试: 权限提升真实有效

  4. C# ModBus Tcp读写数据 与服务器进行通讯

    前言 本文将使用一个NuGet公开的组件技术来实现一个ModBus TCP的客户端,方便的对Modbus tcp的服务器进行读写,这个服务器可以是电脑端C#设计的,也可以是PLC实现的,也可以是其他任 ...

  5. jQuery-2.DOM---节点插入

    DOM内部插入append()与appendTo() 动态创建的元素是不够的,它只是临时存放在内存中,最终我们需要放到页面文档并呈现出来.那么问题来了,怎么放到文档上? 这里就涉及到一个位置关系,常见 ...

  6. 【转载】 TensorflowOnSpark:1)Standalone集群初体验

    原文地址: https://blog.csdn.net/jiangpeng59/article/details/72867368 作者:PJ-Javis 来源:CSDN --------------- ...

  7. 通过位运算求两个数的和(求解leetcode:371. Sum of Two Integers)

    昨天在leetcode做题的时候做到了371,原题是这样的: 371. Sum of Two Integers Calculate the sum of two integers a and b, b ...

  8. 添加mtdparts引起的问题

    今天在给uboot添加分区,大家都知道添加完之后直接在终端里面mtd会报错: SMDK2440 # mtd mtdparts variable not set, see 'help mtdparts' ...

  9. 【转】python两个 list 获取交集,并集,差集的方法

    1. 获取两个list 的交集: #方法一: a=[2,3,4,5] b=[2,5,8] tmp = [val for val in a if val in b] print tmp #[2, 5] ...

  10. OpenLDAP一登录系统就修改密码

    1:修改配置文件 在前面打开注释 moduleload ppolicy.la modulepath /usr/lib/openldap modulepath /usr/lib64/openldap   ...