spring 之 注入之 by name or by type, or both ?
@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 ?的更多相关文章
- Spring自动注入properties文件
实现spring 自动注入属性文件中的key-value. 1.在applicationContext.xml配置文件中,引入<util />命名空间. xmlns:util=" ...
- spring 属性注入
Spring的核心技术室依赖注入,下面是依赖注入之属性注入的实现过程,牛刀小试,请看效果. 1.首先添加Spring.Web引用.本例中是使用分层思想来演示的,下面是项目的结构和UserModel类的 ...
- spring 多线程 注入 服务层 问题
在用多线程的时候,里面要用到Spring注入服务层,或者是逻辑层的时候,一般是注入不进去的.具体原因应该是线程启动时没有用到Spring实例不池.所以注入的变量值都为null. 详细:http://h ...
- Spring 依赖注入方式详解
平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...
- Spring的注入问题
作下笔记,Spring的注入问题[多个实例问题] 解决方案如下: package student.life.support.platform.service.impl; import javax.an ...
- Spring依赖注入(IOC)那些事
小菜使用Spring有几个月了,但是对于它的内部原理,却是一头雾水,这次借着工作中遇到的一个小问题,来总结一下Spring. Spring依赖注入的思想,就是把对象交由Spring容器管理,使用者只需 ...
- Spring依赖注入三种方式详解
在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...
- Spring依赖注入:注解注入总结
更多11 spring 依赖注入 注解 java 注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.S ...
- Spring 依赖注入,在Main方法中取得Spring控制的实例
Spring依赖注入机制,在Main方法中通过读取配置文件,获取Spring注入的bean实例.这种应用在实训的时候,老师曾经说过这种方法,而且学Spring入门的时候都会先学会使用如何在普通的jav ...
随机推荐
- layui布局器网站工具
http://layuiout.magicalcoder.com/magicaldrag-admin/drag
- PLSQL Developer连接Oracle
1.安装PLSQL Developer Oracle数据库和PL/SQL Developer的安装步骤,这里就不做叙述了,百度安装方法的时候有说在安装PL/SQL Developer软件时,不要安装在 ...
- tail语法
本文介绍Linux下tail命令的使用方法.linux tail命令用途是依照要求将指定的文件的最后部分输出到标准设备,通常是终端,通俗讲来,就是把某个档案文件的最后几行显示到终端上,假设该档案有更新 ...
- 蓝牙协议分析(10)_BLE安全机制之LE Encryption
1. 前言 前面文章介绍了两种BLE的安全机制:白名单[4]和LL privacy[3].说实话,在这危机四伏的年代,这两种“捂着脸讲话(其它人不知道是谁在讲话,因而不能插话.不能假传圣旨,但讲话的内 ...
- Linux 驱动——Led驱动1
led_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/init ...
- 环境搭建、RF库
一.Python27安装 1.双击安装python-2.7.13-64位.msi 2.检查python:cmd命令行→[python]→回车,出现如图所示,表示成功 可能出现:'python'不是内部 ...
- flask自定义处理错误方法
自定义错误处理方法: 当客户端访问浏览器是,得到相对应的状态码,服务器通过状态码给用户相对应的页面. @app.errorhandler(404) def handle_404_error(err): ...
- linux samba smb 在客户端无法连接使用
netstat -nutlp查看是否启动进程 1.网络是否正常,是否可以ping通.2.Windows和Linux的防火墙全部关闭.3.samba的端口是否开启,tcp/139.tcp/445.udp ...
- 在windows上使用ssh秘钥连接git服务器
git部署在centos7上 安装好git后,新建一个用户test(注意要加入git用户组)配置ssh秘钥登录,我的另一篇博客有写配置步骤 重点的地方是在windows系统上使用秘钥登录git服务器 ...
- [JAVA]JAVA多线程实现方法之——实现Runnable接口
public class MultiThread { public static void main(String[] args) { Thread t1 = new Thread(new Threa ...