Spring提供了四种类型的自动装配策略:

  • byName – 把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。
  • byType – 把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。
  • constructor – 把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean的对应属性中。
  • autodetect – 首先使用costructor进行自动装配。如果失败,再尝试使用byType进行自动装配。

我这里以关羽和青龙偃月刀为例: 首先定义一个武器接口Weapon:

package com.moonlit.myspring;public interface Weapon {public void attack();
}

然后定义一个Weapon接口的实现Falchion类:

package com.moonlit.myspring;public class Falchion implements Weapon {public void attack() {System.out.println("falcon is attacking!");}
}

定义一个英雄接口Hero:

package com.moonlit.myspring;public interface Hero {public void perform();
}

然后定义一个Hero接口的实现Guanyu类(代表关羽):

package com.moonlit.myspring;public class GuanYu implements Hero {private Weapon weapon;public void perform() {System.out.println("GuanYu pick up his weapon.");weapon.attack();}public Weapon getWeapon() {return weapon;}public void setWeapon(Weapon weapon) {this.weapon = weapon;}
}

在不涉及自动装配的情况下,我们想要通过Spring的DI将Fachion类对象注入到Guanyu类的weapon属性中,可以新建一个xml文件(我这里取名为spring-idol.xml)并在里面填写:

spring-idol.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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="falchion" class="com.moonlit.myspring.Falchion" /><bean id="guanyu" class="com.moonlit.myspring.GuanYu"><property name="weapon" ref="falchion" /></bean></beans>

其中最主要的内容就是两个bean的声明部分:

  <bean id="falchion" class="com.moonlit.myspring.Falchion" /><bean id="guanyu" class="com.moonlit.myspring.GuanYu"><property name="weapon" ref="falchion" /></bean>

第一个bean标签定义了一个Falchion类型的bean,第二个bean标签中将第一个bean作为weapon的值装配到了weapon属性中。 然后我们可以写一个测试程序来查看效果:

package com.moonlit.practice;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.moonlit.myspring.Hero;public class AutowirePractice {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-idol.xml");Hero guanyu = (Hero) context.getBean("guanyu");guanyu.perform();}
}

输出结果如下:

GuanYu pick up his weapon.
falcon is attacking!

到目前为止还没有涉及到自动装配的内容,接下来开始讲述自动装配的内容。

byName自动装配

改变spring-idol.xml中bean声明内容的形式如下:

  <bean id="weapon" class="com.moonlit.myspring.Falchion" /><bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byName" />

得到一样的结果。

我们将Falchion类的id去了一个和Guanyu类的属性weapon一样的名字,并且在guanyu bean中添加了autowire="byName"用于指明装配类型是byName自动装配。这个时候guanyu bean就是在上下文中找名为weapon的bean装配到他自己的weapon属性中。

byType自动装配

改变spring-idol.xml中bean声明内容的形式如下:

  <bean id="falchion" class="com.moonlit.myspring.Falchion" /><bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byType" />

得到一样的结果。

这里我们已经不用关注Falchion类对应的bean的id是什么了,因为我们已经定义guanyu bean的autowire属性为"byType"。这个时候guanyu bean会在上下文中寻找和weapon具有相同类型的类对应的bean。
因为Guanyu类的weapon实现Weapon借口,整个上下文中目前只有一个Weapon接口的实现Falchion类,所以以"byType"类型就检测到了falchion bean并将其注入到了guanyu bean的weapon属性中。
但是也会出现一种情况就是检测的时候可能会出现多个相同type的bean,这个时候就不知道要装配那个了。比如,我在新建一个实现Weapon接口的方天画戟类HalBerd:

package com.moonlit.myspring;public class Halberd implements Weapon {public void attack() {System.out.println("halberd is attacking!!!");}
}

并且在xml文件中声明一个新的halberd bean:

<bean id="halberd" class="com.moonlit.myspring.Halberd" />

在这种情况下就会出错,因为有两个bean满足byType的结果。

这个时候有两种解决办法:
第一种方法是将其中一个bean的primary属性设为false,比如:我们将方天画戟falchion bean的primary属性设为true,以防冠以使用方天画戟(很好奇吕布死了之后,赤兔马归关羽了,方天画戟去哪里了):

  <bean id="falchion" class="com.moonlit.myspring.Falchion"  /><bean id="halberd" class="com.moonlit.myspring.Halberd" primary="true" /><bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byType" />

输出结果如下:

GuanYu pick up his weapon.
halberd is attacking!!!

从输出结果中可以看到,关羽没有使用青龙偃月刀,而是使用方天画戟进行攻击了。

注:我看的Spring实战(第3版)上面说bean的默认primary属性默认是true,但是我这里用的是spring 4,根据效果来看primary的默认属性应该是false。
第二种方法是设置其中一个bean的autowire-candidate属性为false,比如:我们将方天画戟的autowire-candidate属性设为false:

  <bean id="falchion" class="com.moonlit.myspring.Falchion"  /><bean id="halberd" class="com.moonlit.myspring.Halberd" primary="true" autowire-candidate="false" /><bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byType" />

这个时候测试程序的输出如下:

GuanYu pick up his weapon.
falcon is attacking!

可以看到这个时候关羽又重拾了青龙偃月刀。可以看到,当halberd bean的autowire-candidate属性设为false时,他将不会作为自动装配的竞选bean之一,这个时候虽然halberd的primary属性为true,但是halberd bean没有参与自动装配的竞选,所以自动装配到了falchion。

这种感觉就好像:“隔壁村李小花觊觎我已久,但我是一个要成为海贼王的男人,于是拒绝了她……最终她嫁给了隔壁老王,过上了幸福的生活”。

constructor自动装配

演示constructor之前我需要在在GuanYu类中添加一个构造函数:

    public GuanYu(Weapon weapon) {this.weapon = weapon;}

在xml文件中设置guanyu bean的autowire属性为constructor:

  <bean id="falchion" class="com.moonlit.myspring.Falchion"  /><bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="constructor" />

输出结果如下:

GuanYu pick up his weapon.
falcon is attacking!

实现了自动装配。

最佳自动装配

书上说是将autowire属性设为autodetect,但是我发现在我使用的spring 4(我看的书是spring 3)版本中没有autodetect,autowire属性只有byName,byType,constructor,default,no这些属性。

默认自动装配

可以在beans标签中添加default-autowire属性来设置默认自动装配策略,如:在beans标签中添加default-autowire="byType"设置默认自动装配策略为byType自动装配。

混合使用自动装配和显示装配

为了演示这个效果,我为Guanyu类添加了一个String成员变量name,虽然关羽就叫关羽,但是人家称呼他的时候还是会称呼他云长之类的。新定义的GuanYu类如下:

package com.moonlit.myspring;public class GuanYu implements Hero {private String name;private Weapon weapon;
//  public GuanYu(String name, Weapon weapon) {
//      this.name = name;
//      this.weapon = weapon;
//  }public void perform() {System.out.println(name + " pick up his weapon.");weapon.attack();}public Weapon getWeapon() {return weapon;}public void setWeapon(Weapon weapon) {this.weapon = weapon;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

(这里我注释掉了GuanYu类的构造函数。)

一个完全显示装配的例子如下:

  <bean id="falchion" class="com.moonlit.myspring.Falchion"  /><bean id="guanyu" class="com.moonlit.myspring.GuanYu"><property name="name"  value="Guan Yun Chang" /><property name="weapon" ref="falchion" /></bean>

当然,我们也可以使用显示装配和自动装配结合,显示装配name,自动装配weapon,如下:

  <bean id="falchion" class="com.moonlit.myspring.Falchion"  /><bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byType"><property name="name"  value="Guan Yun Chang" /></bean>

具有一样效果的输出。

使用混合装配的最后一个注意事项:当使用constructor自动装配策略时,我们必须让Spring自动装配构造器的所有入参——我们不能混合使用constructor自动装配策略和<constructor-arg>元素。

转载于:https://www.cnblogs.com/moonlightpoet/p/5569239.html

Spring学习笔记--自动装配Bean属性相关推荐

  1. Spring学习笔记15--注解Bean

    传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文 ...

  2. Spring学习笔记——@Configuration和@Bean注解

    前言 在Spring框架中,有两种对容器的配置和启动方式,一种是基于XML文档的配置方式,一种则是"零配置",即Java Based Configuration. 而在零配置中,最 ...

  3. 8.Spring学习笔记_使用外部属性文件(by尚硅谷_佟刚)

    使用外部属性文件 在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离 S ...

  4. Spring中的自动装配和Autowired

    彻底搞明白Spring中的自动装配和Autowired 一.自动装配 当Spring装配Bean属性时,有时候非常明确,就是需要将某个Bean的引用装配给指定属性.比如,如果我们的应用上下文中只有一个 ...

  5. 【Spring学习笔记 四】Spring自动装配机制实践

    我们一般学习某个知识,一定会现有个较为复杂的配置让你理解其中的关系,这个配置清晰规整,但是可能会需要大量的配置,这个时候就会有约定大于配置的理论实现了,通过我们约定好的一致的名称,我可以少写很多对应关 ...

  6. (Spring)自动装配bean

    文章目录 自动装配bean 1. 环境搭建 2. byName自动装配 3. byType自动装配 4. 使用注解自动装配 4.1 @Autowired和@Qualifier 4.2 @Resourc ...

  7. Spring自动装配Bean

    除了使用 XML 和 Annotation 的方式装配 Bean 以外,还有一种常用的装配方式--自动装配.自动装配就是指 Spring 容器可以自动装配(autowire)相互协作的 Bean 之间 ...

  8. java 自动装载_java_详解Java的Spring框架下bean的自动装载方式,Spring容器可以自动装配相互协 - phpStudy...

    详解Java的Spring框架下bean的自动装载方式 Spring容器可以自动装配相互协作bean之间的关系,这有助于减少对XML配置,而无需编写一个大的基于Spring应用程序的较多的和元素. 自 ...

  9. Spring4-自动装配Beans-按属性的数据类型自动装配Bean

    1.创建Maven项目,项目名称springdemo16,如图所示 2.配置Maven,修改项目中的pom.xml文件,修改内容如下 <project xmlns="http://ma ...

最新文章

  1. 用一条sql语句删除表中所相同记录
  2. Java实战项目开发学习书籍
  3. Maven 强制导入jar包
  4. go爬虫和python爬虫哪个好_python 爬虫实战项目--爬取京东商品信息(价格、优惠、排名、好评率等)-Go语言中文社区...
  5. 收获,不止SQL优化——抓住SQL的本质--第七章
  6. 【Python3网络爬虫开发实战】1.2.5-PhantomJS的安装
  7. 关于HTML+CSS常用标签
  8. 设置hash后导致的返回问题的解决方案
  9. c语言实现动画的方法,C语言动画技术的实现方法
  10. uva10859 Placing Lampposts
  11. docker-elastic7.9.3集群搭建并开启用户验证
  12. 苍穹插件常用事件与方法
  13. MySQL数据完整性约束
  14. 谁有全民一起mysql_我是Redis,MySQL大哥被我害惨了!
  15. iOS .Crash文件符号化
  16. [转]什么样的女人才是老婆
  17. java swing 表格控件_java swing 开发 -JTable
  18. 【深度学习】QA机器人的实现
  19. 编程新手如何快速提升coding能力?
  20. 方波正弦波(幅移键控发生器ASK)电路设计

热门文章

  1. *【HDU - 2819】Swap(二分图匹配,输出路径)(待证明:是否是最少交换次数?)
  2. 【CF#2A】Winner(模拟 STL-map)☆
  3. Django框架(展示图书信息简易版)
  4. javascript递归遍历文件夹下面的所有文件并返回所有文件全路径名称数组以及解析JavaScript方法体字符串的结束位置
  5. java技术难点_Java核心技术第四章----对象与类重难点总结
  6. 学习笔记18-C语言-文件
  7. leetcode771. 宝石与石头 py永远的神!
  8. 数据结构和算法(02)---字符串(c++)
  9. STL源码剖析 序列式容器|Vector
  10. 对于以太坊虚拟机 (EVM)及其相关知识的讲解