Spring9 : Autowire(自动装配)机制
原文出处: 五月的仓颉
为什么Spring要支持Autowire(自动装配)
先写几个类,首先定义一个Animal接口表示动物:
1
2
3
4
5
|
public interface Animal { public void eat(); } |
写一个Animal接口的实现Tiger类:
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Tiger implements Animal { @Override public void eat() { System.out.println( "Tiger.eat()" ); } @Override public String toString() { return "I'm a tiger" ; } } |
写一个动物园类Zoo,持有Animal接口,表示动物园中有动物:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class Zoo { private Animal animal; public Animal getAnimal() { return animal; } public void setAnimal(Animal animal) { this .animal = animal; } @Override public String toString() { if (animal == null ) { return null ; } return animal.toString(); } } |
配置一下spring文件,由于这个功能研究的是Autowire,因此我命名为autowire.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?xml version= "1.0" encoding= "UTF-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id= "tiger" class = "org.xrq.action.by.Tiger" /> <bean id= "zoo" class = "org.xrq.action.by.Zoo" > <property name= "animal" ref= "tiger" /> </bean> </beans> |
Spring引入Autowire(自动装配)机制就是为了解决<bean>标签下<property>标签过多的问题,<property>标签过多会引发两个问题:
- 如果一个Bean中要注入的对象过多,比如十几二十个(这是很正常的),那将导致Spring配置文件非常冗长,可读性与维护性差
- 如果一个Bean中要注入的对象过多,配置麻烦且一不小心就容易出错
因此,为了解决使用<property>标签注入对象过多的问题,Spring引入自动装配机制,简化开发者配置难度,降低xml文件配置大小。
使用Autowire去除<property>标签
下面来看一下使用Autowire去除<property>,autowire有两处点:
- 可以配置在<beans>根标签下,表示对全局<bean>起作用,属性名为default-autowire
- 可以配置在<bean>标签下,表示对当前<bean>起作用,属性名为autowire
通常都是在<beans>根标签下配置自动装配比较多,default-autowire有四种取值:
- no:默认,即不进行自动装配,每一个对象的注入比如依赖一个<property>标签
- byName:按照beanName进行自动装配,使用setter注入
- byType:按照bean类型进行自动装配,使用setter注入
- constructor:与byType差不多,不过最终属性通过构造函数进行注入
这里研究的是去除<property>标签,因此第一种不管;constructor装配不太常用,因此这里也不管,重点看最常用的byName与byType,至于具体使用哪种根据自己的业务特点进行相应的设置。
首先看一下byName,byName意为在spring配置文件中查询beanName与属性名一致的bean并进行装配,若类型不匹配则报错,autowire.xml如果使用byName进行属性装配,那么将改成以下的形式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?xml version= "1.0" encoding= "UTF-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd" default -autowire= "byName" > <bean id= "animal" class = "org.xrq.action.by.Tiger" /> <bean id= "zoo" class = "org.xrq.action.by.Zoo" /> </beans> |
看到Zoo中有一个名为animal的属性,我将Tiger这个bean也命名为animal,由于Tiger是Animal接口的实现类,因此Spring可以找到beanName为animal的bean并自动装配到Zoo的animal属性中,这就是byName的自动装配形式。
接着看一下byType的自动装配形式,byType意为在spring配置文件中查询与属性类型一致的bean并进行装配,若有多个相同类型则报错(下一部分讲),autowire.xml如果使用byType进行属性装配,那么将改成以下的形式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?xml version= "1.0" encoding= "UTF-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd" default -autowire= "byType" > <bean id= "tiger" class = "org.xrq.action.by.Tiger" /> <bean id= "zoo" class = "org.xrq.action.by.Zoo" /> </beans> |
将Tiger命名为tiger(将bean命名为类名首字母小写也比较符合规范),由于Tiger是Animal接口的实现类,因此Spring找到了Tiger并自动装配到Zoo的animal属性中,这就是byType的自动装配形式。
byType装配出现多个相同类型的bean及解决方案
前面演示了,byType的装配方式是在Spring配置文件中寻找属性类型与bean类型一致的bean,那么有一个问题,就是如果属性类型在Spring配置文件中有多个相同类型的bean会出现什么样的情况?为了探究一下这个问题,先定义另外一个Animal接口的实现类,叫做lion:
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Lion implements Animal { @Override public void eat() { System.out.println( "Lion.eat()" ); } @Override public String toString() { return "I'm a lion" ; } } |
接着,在Spring配置文件中定义一下Lion这个类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?xml version= "1.0" encoding= "UTF-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd" default -autowire= "byType" > <bean id= "tiger" class = "org.xrq.action.by.Tiger" /> <bean id= "lion" class = "org.xrq.action.by.Lion" /> <bean id= "zoo" class = "org.xrq.action.by.Zoo" /> </beans> |
运行一个测试类,结果为:
1
2
3
4
5
6
7
8
9
|
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'zoo' defined in class path resource [spring/autowire.xml]: Unsatisfied dependency expressed through bean property 'animal' : : No unique bean of type [org.xrq.action.by.Animal] is defined: expected single matching bean but found 2 : [tiger, lion]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.xrq.action.by.Animal] is defined: expected single matching bean but found 2 : [tiger, lion] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java: 1166 ) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java: 1058 ) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java: 516 ) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java: 455 ) at org.springframework.beans.factory.support.AbstractBeanFactory$ 1 .getObject(AbstractBeanFactory.java: 293 ) |
意思很明显:想要通过byType方式为animal进行装配却找到了两个符合要求的bean,分别为tiger与lion,这导致了没有唯一的bean可以对animal进行装配。
这个问题有两种解决方案,假如现在我要装配的是lion这个bean,第一种解决方案是将不需要进行自动装配的bean进行排除,对不需要进行自动装配的bean设置属性autowire-candidate=”false”即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?xml version= "1.0" encoding= "UTF-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd" default -autowire= "byType" > <bean id= "tiger" class = "org.xrq.action.by.Tiger" autowire-candidate= "false" /> <bean id= "lion" class = "org.xrq.action.by.Lion" /> <bean id= "zoo" class = "org.xrq.action.by.Zoo" /> </beans> |
candidate顾名思义,即候选人的意思,autowire-candidate=”false”即这个bean我不想让它作为自动装配的候选者,既然tiger不是自动装配的候选者,那么animal类型在Spring容器中能自动装配的也就只有一个lion了,Spring自动装配lion,不会有问题。
第一种思路是排除那些不需要作为自动装配候选者的bean,第二种思路就从相反逻辑出发,设置当发现有多个候选者的时候优先使用其中的哪个候选者,对要作为自动装配候选者的bean设置primary=”true”即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?xml version= "1.0" encoding= "UTF-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd" default -autowire= "byType" > <bean id= "tiger" class = "org.xrq.action.by.Tiger" /> <bean id= "lion" class = "org.xrq.action.by.Lion" primary= "true" /> <bean id= "zoo" class = "org.xrq.action.by.Zoo" /> </beans> |
这种方式同样也可以将lion装配到animal属性中而不会报错。
from: http://www.importnew.com/24731.html
Spring9 : Autowire(自动装配)机制的更多相关文章
- Spring(五)--autowire自动装配和spel
autowire自动装配和spel 1.需要的实体类 2.需要的配置文件 <?xml version="1.0" encoding="UTF-8"?> ...
- 【面试普通人VS高手系列】Spring Boot中自动装配机制的原理
最近一个粉丝说,他面试了4个公司,有三个公司问他:"Spring Boot 中自动装配机制的原理" 他回答了,感觉没回答错误,但是怎么就没给offer呢? 对于这个问题,看看普通人 ...
- [转载]Spring Autowire自动装配介绍
转自: http://www.cnblogs.com/zhishan/p/3190757.html 在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象.但是对于一个大型 ...
- Spring Autowire自动装配介绍
在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象.但是对于一个大型的系统,这个操作将会耗费我们大量的资源,我们不得不花费大量的时间和精力用于创建和维护系统中的< ...
- Spring Autowire自动装配
在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象.但是对于一个大型的系统,这个操作将会耗费我们大量的资源,我们不得不花费大量的时间和精力用于创建和维护系统中的< ...
- spring bean autowire自动装配
转自:http://blog.csdn.net/xiao_jun_0820/article/details/7233139 autowire="byName"会自动装配属性与Bea ...
- Spring系列7:`autowire`自动装配怎么玩
回顾 前几篇我们介绍各种依赖依赖注入,都是显式指定的,配置明确但同时也有些繁杂和重复."很多发明的出发点,都是为了偷懒,懒人是推动社会进步的原动力".Spring 提供了自动注入依 ...
- 隐式的bean发现与自动装配机制
使用beans.xml文件进行bean的创建和注入通常是可行的,但在便利性上Spring提供了更简单的方法--自动装配 接下来我们假设一个场景:我有若干播放器(MediaPlayer{CD播放器/MP ...
- Spring 自动装配机制
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w ...
- 深度剖析Spring Boot自动装配机制实现原理
在前面的分析中,Spring Framework一直在致力于解决一个问题,就是如何让bean的管理变得更简单,如何让开发者尽可能的少关注一些基础化的bean的配置,从而实现自动装配.所以,所谓的自动装 ...
随机推荐
- Ionic实战七:Ionic 音乐以及社交页面
Ionic 音乐以及社交页面,可以用于二次开发,也可以用于社交或者音乐app页面模板,但是不足的是图片没法预览.      
- 第一个iOS程序:Hello iOS
今天我们来创建第一个iOS程序:Hello iOS!不需要写任何代码就能实现:
- scp和rsync的区别和常用参数
一.scp 命令 1.scp 是 secure copy 的缩写,用于远程的文件的复制. 2.参数: -r: 递归复制整个目录. 3.实例: scp /home/space/music/1.mp3 u ...
- CSUOJ 1900 锋芒不露
Description 小闪最近迷上了二刀流--不过他耍的其实是剑--新买了一个宝库用来专门存放自己收集的双剑.一对剑有两把,分只能左手用的和只能右手用的,各自有一个攻击力数值.虽然一对剑在小闪刚拿到 ...
- sort sign numeric
//JS001 EXEC PGM=SORT //* ...
- MySQL 类型转换
1.问题描述 在项目中遇到要将Int类型转为Char类型,然后利用转化后的Char类型进行模糊查询. 例:合同编号在数据库中为int类型 8066 用利用 806 模糊查询出合同编号为8066数据记录 ...
- CentOS的利手:“Screen”一个可以在多个进程之间多路复用一个物理终端的窗口管理器
你是不是经常需要远程登录到Linux服务器?你是不是经常为一些长时间运行的任务头疼?还在用 nohup 吗?那 么来看看 screen 吧,它会给你一个惊喜! 你是不是经常需要 SSH 或者 tele ...
- Codeforces Round #361 (Div. 2) C. Mike and Chocolate Thieves 二分
C. Mike and Chocolate Thieves 题目连接: http://www.codeforces.com/contest/689/problem/C Description Bad ...
- HDU 4267 A Simple Problem with Integers 多个树状数组
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K ...
- Git_git的诞生
很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了. Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与 ...