为什么Spring要支持Autowire(自动装配)

先写几个类,首先定义一个Animal接口表示动物:

 public interface Animal {

     public void eat();

 }

写一个Animal接口的实现Tiger类:

 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接口,表示动物园中有动物:

 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:

 <?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进行属性装配,那么将改成以下的形式:

 <?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进行属性装配,那么将改成以下的形式:

 <?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:

 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这个类:

 <?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>

运行一个测试类,结果为:

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 : [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 : [tiger, lion]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory$.getObject(AbstractBeanFactory.java:)

意思很明显:想要通过byType方式为animal进行装配却找到了两个符合要求的bean,分别为tiger与lion,这导致了没有唯一的bean可以对animal进行装配。

这个问题有两种解决方案,假如现在我要装配的是lion这个bean,第一种解决方案是将不需要进行自动装配的bean进行排除,对不需要进行自动装配的bean设置属性autowire-candidate="false"即可

 <?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"即可

 <?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属性中而不会报错。

Spring9:Autowire(自动装配)机制的更多相关文章

  1. Spring(五)--autowire自动装配和spel

    autowire自动装配和spel 1.需要的实体类 2.需要的配置文件 <?xml version="1.0" encoding="UTF-8"?> ...

  2. 【面试普通人VS高手系列】Spring Boot中自动装配机制的原理

    最近一个粉丝说,他面试了4个公司,有三个公司问他:"Spring Boot 中自动装配机制的原理" 他回答了,感觉没回答错误,但是怎么就没给offer呢? 对于这个问题,看看普通人 ...

  3. [转载]Spring Autowire自动装配介绍

    转自: http://www.cnblogs.com/zhishan/p/3190757.html 在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象.但是对于一个大型 ...

  4. Spring Autowire自动装配介绍

    在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象.但是对于一个大型的系统,这个操作将会耗费我们大量的资源,我们不得不花费大量的时间和精力用于创建和维护系统中的< ...

  5. Spring Autowire自动装配

    在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象.但是对于一个大型的系统,这个操作将会耗费我们大量的资源,我们不得不花费大量的时间和精力用于创建和维护系统中的< ...

  6. spring bean autowire自动装配

    转自:http://blog.csdn.net/xiao_jun_0820/article/details/7233139 autowire="byName"会自动装配属性与Bea ...

  7. Spring系列7:`autowire`自动装配怎么玩

    回顾 前几篇我们介绍各种依赖依赖注入,都是显式指定的,配置明确但同时也有些繁杂和重复."很多发明的出发点,都是为了偷懒,懒人是推动社会进步的原动力".Spring 提供了自动注入依 ...

  8. 隐式的bean发现与自动装配机制

    使用beans.xml文件进行bean的创建和注入通常是可行的,但在便利性上Spring提供了更简单的方法--自动装配 接下来我们假设一个场景:我有若干播放器(MediaPlayer{CD播放器/MP ...

  9. Spring 自动装配机制

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w ...

  10. 深度剖析Spring Boot自动装配机制实现原理

    在前面的分析中,Spring Framework一直在致力于解决一个问题,就是如何让bean的管理变得更简单,如何让开发者尽可能的少关注一些基础化的bean的配置,从而实现自动装配.所以,所谓的自动装 ...

随机推荐

  1. Go学习笔记02-源码

    第二部分 源码 基于 Go 1.4,相关文件位于 src/runtime 目录.文章忽略了 32bit 代码,有兴趣的可自行查看源码文件.为便于阅读,示例代码做过裁剪. 1. Memory Alloc ...

  2. nodejs和npm的安装

    下载nodejs的压缩包 网址:https://nodejs.org/en/ 下载以tar.xz结尾的包例如:node-v8.9.4-linux-x64.tar.xz 上传包到制定的目录 可以用lrz ...

  3. 三、scrapy后续

    CrawlSpiders 通过下面的命令可以快速创建 CrawlSpider模板 的代码: scrapy genspider -t crawl tencent tencent.com 我们通过正则表达 ...

  4. spring注解-@Transactional事务几点注意

    这里面有几点需要大家留意:A. 一个功能是否要事务,必须纳入设计.编码考虑.不能仅仅完成了基本功能就ok.B. 如果加了事务,必须做好开发环境测试(测试环境也尽量触发异常.测试回滚),确保事务生效.C ...

  5. Mysql引擎中MyISAM和InnoDB的区别有哪些?

    简单的概括一下 InnoDB:支持事务处理等不加锁读取支持外键支持行锁不支持FULLTEXT类型的索引不保存表的具体行数,扫描表来计算有多少行DELETE 表时,是一行一行的删除InnoDB 把数据和 ...

  6. 蚂蚁爬杆问题 UVA 10881

    算法入门经典训练指南上的题. 这里有必要讲一下蚂蚁爬杆问题:每只蚂蚁都有一个初始方向,相撞会转向,关键就是相撞的处理,由于速度并不会改变,两只蚂蚁相撞,可以看做,两只蚂蚁穿过对方,继续沿原方向前进,经 ...

  7. hadoop源码调试

    原文地址:http://www.cnblogs.com/end/archive/2011/04/26/2029497.html 在使用hadoop的时候,可能遇到各种各样的问题,然而由于hadoop的 ...

  8. Centos安装jdk8

    1.下载jdk1.8的tar cd /usr/local/src #切换到该目录下 wget url #下载jdk8的tar包 2.下载完成后解压tar包 tar -zxvf jdk-8u152-li ...

  9. 为什么说DOM操作很慢

    转自http://www.cnblogs.com/yuzhongwusan/articles/5275933.html   一直都听说DOM很慢,要尽量少的去操作DOM,于是就想进一步去探究下为什么大 ...

  10. Android的OkHttp开源框架的使用方法

    前段时间研究了下Android里面非常火爆的网络请求库OkHttp,这篇文章主要来介绍下OkHttp的常用请求的使用方式,后面一篇文章会介绍本人基于OkHttp封装的一个操作更简单.更适用于项目的网络 ...