在Spring中,对象不负责寻找和创建它们需要的其他对象。创建两个应用对象之间关联的动作是依赖注入的核心功能,通常称为装配。

  创建beans和构建它们之间的关系是Spring的责任,但是告诉Spring哪些bean需要被创建并且怎样将它们装装配到一起是开发者的责任。Spring提供了三种基本的装配机制。

  •  显式地通过XML配置
  • 显式地通过Java配置
  • 隐式地发现bean并且自动装配

自动装配beans

  Spring从两个角度解决自动装配

  • Component scanning----Spring自动发现beans并在容器中创建
  • Autowiring-----Spring自动构建bean的依赖
组件扫描

  组件扫描不是默认开启项,需要显式配置以便Spring寻找带有@Component注解的类并创建它们。@Component注解可以在它的属性中标注bean的ID。例如,@Component("id"),如果没有显式标注ID,那么Spring会将这个bean的ID设为类名并将首字母小写。基于Java配置如下:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}

除此之外,可以用Java Dependency Injection specification(JSR-330)中的注解@Named为bean提供ID。Spring支持将@Named替换@Component。

  如果没有更多配置@ComponentScan将会默认扫描与配置类所在包相同的类。但是,应该显式地设置扫描的base package,因为那样你可以将所有的配置代码归置到一个包中,区别于应用代码。例如这样@ComponentScan("basepackagename")、或者@ComponentScan(basePackages="soundsystem"),多个包的情况,@ComponentScan(basePackages={"soundsystem", "video"})。用上述String形式配置base package时,并不是类型安全的,如果重构包名,指定的base package将会出错,因此@ComponentScan可以通过base package中的类或者接口定义base package,如:@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})

  基于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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="soundsystem" />
</beans>

自动装配

  如果应用程序中所有的对象都是独立的,没有依赖的,那么组建扫描就能完成所需功能。但是如果对象包含对其他对象的依赖,那么自动装配就能派上用场了。

  @Autowired注解可以用在构造函数、属性的setter方法甚至任何方法上。无论构造函数、setter方法或其他任何方法,Spring将会尝试构建参数的依赖。仅当有且仅有一个bean匹配,才会将这个bean装配。如果没有bean匹配,Spring会在容器创建时抛出一个异常。为了避免这个异常你可以设置@Autowired的required属性为false,@Autowired(required=false)。当required属性为false时,Spring将会进行自动装配,但是如果没有bean匹配,会使需要注入依赖关系的bean未装配。你应该十分谨慎地设置required属性为false。bean的属性未被装配,有可能发生空指针异常。如果有多个bean匹配,Spring将会抛出异常表示出现歧义现象。

  同样的,可以用Java Dependency Injection specification中的注解@Inject代替@Autowired。

通过Java装配bean

  尽管通过自动装配的方式构造依赖很方便,但是有时我们必须显式地配置Spring。比如,需要从第三方类库中装配一些组件进入你自己的应用。因为你无法获取源码,所以没有机会在类上标记@Component和@Autowired注解。

  Java方式配置优于XML方式的配置,它更强大,类型安全,方便重构。

  创建一个JavaConfig类的关键在于用@Configuration注解标记它。通过编写一个创建所需类型实例的方法并且用@Bean标记它的方式在JavaConfig中声明一个bean。

@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}

  默认地,bean的ID会被设置为同@Bean注解标识的方法名称一样。也可以指定ID,@Bean(name="lonelyHeartsClubBand")。

  如果一个bean需要依赖其他对象,最简单的装配方法是引用被依赖对象的方法,如下:

@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}

  cdPlayer方法与sgtPeppers方法有着微妙的不同,CDPlayer对象是通过调用接受CompactDisc对象作为参数的构造方法来创建的,而不是通过默认构造方法。貌似CompactDisc对象是通过调用sgtPeppers来构造的,但并不是这样。因为sgtPeppers()方法被注解了@Bean,Spring将会拦截任何对它的调用,以确保由sgtPeppers()方法生成的对象已经被返回了,而不是允许sgtPeppers()又一次被调用。例如:

@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}
@Bean
public CDPlayer anotherCDPlayer() {
return new CDPlayer(sgtPeppers());
}

  如果对sgtPeppers()方法的调用与其他Java方法一样,那么每一个CDPlayer将会拥有自己的SgtPeppers实例。默认情况下,Spring的beans都是单例的。所以Spring拦截对sgtPeppers()方法的调用以确保返回的是由Spring自己调用sgtPeppers()方法生成的CompactDisc Bean。因此,两个CDPlayer Bean拥有相同的SgtPeppers实例。

  这样做法很迷惑,下面是一种更简单和容易理解的方法。

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}

  cdPlayer方法接受一个CompactDisc对象作为参数。当Spring调用cdPlayer方法生成CDPlayer Bean时,将会自动装配一个CompactDisc对象进入cdPlayer方法。

  如果需要通过setter方法的方式实现DI,如下:

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
CDPlayer cdPlayer = new CDPlayer(compactDisc);
cdPlayer.setCompactDisc(compactDisc);
return cdPlayer;
}

通过XML装配bean

<?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.xsd
http://www.springframework.org/schema/context">
<!-- configuration details go here -->
</beans>

  相当于@Configuration

<bean class="soundsystem.SgtPeppers" />

  相当于@Bean,如果没有指定ID会被默认命名为全称限定名,此例中为soundsystem.SgtPeppers#0。#0是用来区分类型相同bean的编号。最好指定ID

<bean id="compactDisc" class="soundsystem.SgtPeppers" />

  首先值得注意的是,不像在JavaConfig中,你直接负责创建一个SgtPeppers实例。当Spring看见<bean>元素,它会通过默认构造函数帮你创建一个SgtPeppers bean。用XML配置Bean创建更加被动。

  另外一件值得注意的是,bean的类型通过class属性的字符串设置。但是谁能保证class属性指向一个真的类?Spring的XML配置无法在编译期验证指向的Java类型。甚至于,如果你重命名了这个类,它将指向一个不存在的类。

  在SpringXML配置中,只有一种方法声明bean,通过<bean>元素。但是当通过XML声明DI,将会有几种方式和风格。具体到构造器注入,主要有两种选择:  

  • <constructor-arg>元素
  • 使用Spring3.0中引入的c-namespace

  两者之间的差异是非常复杂的。如你所见,<constructor-arg>元素通常比c-namespace更冗长,在XML中也更难阅读。另一方面,<constructor-arg>元素可以做一些c-namespace做不到的。在构造器注入中,我们将两者作为并列选项。

<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="compactDisc" />
</bean>

  当Spring容器见到<bean>元素,它会创建一个CDPlayer实例。<constructor-arg>元素告诉它传递一个ID是compactDisc的bean的引用给CDPlayer的构造器。当然也可以使用Spring的c-namespace。c-namespace是Spring3.0中引入的一种更简洁的XML中构造器注入方式。如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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.xsd"><bean id="cdPlayer" class="soundsystem.CDPlayer"
c:cd-ref="compactDisc" />
</beans>

  c代表命名空间,cd代表构造器参数名称,-ref是一种命名约定,引入一个名为compactDisc的bean。但是通过参数名称引用bean会产生问题,指向参数位置会更好。

<bean id="cdPlayer" class="soundsystem.CDPlayer"
c:_0-ref="compactDisc" />

  这个比上一个XML看起来还古怪,由于XML不允许数字作为属性的第一个字符,所以用了_作为前缀。如果只有一个参数,可以根本不制定参数

<bean id="cdPlayer" class="soundsystem.CDPlayer"
c:_-ref="compactDisc" />

  通过构造器注入基本类型如下

<bean id="compactDisc"
class="soundsystem.BlankDisc">
<constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
</bean>

  c-namespace方式

<bean id="compactDisc"
class="soundsystem.BlankDisc"
c:_title="Sgt. Pepper's Lonely Hearts Club Band"
c:_artist="The Beatles" />
或
<bean id="compactDisc"
class="soundsystem.BlankDisc"
c:_0="Sgt. Pepper's Lonely Hearts Club Band"
c:_1="The Beatles" />

  <constructor-arg>元素可以做但是c-namespace方式无法实现的是注入容器

<bean id="compactDisc" class="soundsystem.BlankDisc">
<constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<value>Sgt. Pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting Better</value>
<value>Fixing a Hole</value>
<!-- ...other tracks omitted for brevity... -->
</list>
</constructor-arg>
</bean>
或
<constructor-arg>
<list>
<ref bean="sgtPeppers" />
<ref bean="whiteAlbum" />
<ref bean="hardDaysNight" />
<ref bean="revolver" />
...
</list>
</constructor-arg>

  setter方法注入

<bean id="cdPlayer"
class="soundsystem.CDPlayer">
<property name="compactDisc" ref="compactDisc" />
</bean>

  同样的,Spring提供p-namespace代替<property>元素。需要引入如下命名空间。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
...
</bean>

  用p-namespace装配属性,具体含义同c-namespace相同。

<bean id="cdPlayer"
class="soundsystem.CDPlayer"
p:compactDisc-ref="compactDisc" />

  p-namespace无法装配容器。

转载于:https://www.cnblogs.com/m-evan/p/5356077.html

【Core Spring】二、装配beans相关推荐

  1. spring二:装配bean(自动装配)

    创建应用对象之间协作关系的行为通常称为装配(wiring),这就是依赖注入(DI)的本质. Spring提供了三种主要的装配机制: 1. 在xml中进行显式配置.  2. 在java中进行显式配置. ...

  2. Spring自动装配Beans

    在Spring框架,可以用 auto-wiring 功能会自动装配Bean.要启用它,只需要在 <bean>定义"autowire"属性. <bean id=&q ...

  3. Spring(6)---自动装配Beans

    Spring自动装配Beans 在Spring框架,可以用 auto-wiring 功能会自动装配Bean.要启用它,只需要在 <bean>定义"autowire"属性 ...

  4. (二)Spring自动装配

    Spring自动装配 为了减少XML的配置数量.Spring提供了几种技巧来解决这一问题: 自动装配(autowiring): 有助于减少<property>元素和<constroc ...

  5. 一步一步手绘Spring DI运行时序图(Spring 自动装配之依赖注入)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  6. WebService大讲堂之Axis2(7):将Spring的装配JavaBean发布成WebService

    在现今的Web 应用中经常使用Spring 框架来装载JavaBean .如果要想将某些在Spring 中装配的JavaBean 发布成WebService ,使用Axis2 的Spring 感知功能 ...

  7. Spring(3)——装配 Spring Bean 详解

    装配 Bean 的概述 前面已经介绍了 Spring IoC 的理念和设计,这一篇文章将介绍的是如何将自己开发的 Bean 装配到 Spring IoC 容器中. 大部分场景下,我们都会使用 Appl ...

  8. Spring之装配Bean(一)

    Spring中装配bean的三种主要方式 1.隐式的bean发现机制和自动化装配 组件扫描( component scanning) : Spring会自动发现应用上下文中所创建的bean. 自动装配 ...

  9. Spring 自动装配模式之构造函数装配方式

    这种模式与 byType 非常相似,但它应用于构造器参数.Spring 容器看作 beans,在 XML 配置文件中 beans 的 autowire 属性设置为 constructor.然后,它尝试 ...

最新文章

  1. 百度搜索关键字如何排名?“网站SEO”告诉你答案
  2. 无刷新提交表单(非Ajax实现)
  3. 6425C-Lab2 安全高效地管理AD
  4. 项望烽:移动 IM 开发之登录优化
  5. 猫大叫,鼠速逃,人醒了
  6. 数据结构与算法--二叉查找树实现原理
  7. c语言平面向量加法考点,平面向量的加减法怎么死活都不会?有没有什么口诀?例如:向量AB+BC=?向量OA-OB=?向量AB-CB=?有没有什么口诀!...
  8. springMVC接收数据和响应返回
  9. 如何用指针判定系统是32bit还是64bit?一次惨痛的经历,想想都脸红
  10. 拓端tecdat|python算法对音频信号处理Sonification :Gauss-Seidel迭代算法
  11. 解决办法:av_interleaved_write_frame()返回-22 错误
  12. 《生成式深度学习》Generative Deeping Learning 笔记 第二章 深度学习
  13. CentOS6.5 yum源配置
  14. React学习之进阶WEB组件(二十)
  15. macbook 虚拟机安装win7
  16. vue实现拍照人脸识别功能带人脸选中框
  17. 世界时间查询服务器(一)
  18. 高校GIS系统有何作用?
  19. 17正交矩阵和Gram-Schmidt正交化
  20. MTK介绍MTK平台介绍

热门文章

  1. 兄弟||弟兄,以前看过一个“母亲”,现在是“弟兄”,感人!
  2. JavaMelody 1.77.0 发布,Java 应用监控平台
  3. Java排序 - 不实用的几个排序算法 -- 睡眠排序、猴子排序、面条排序、珠排序...
  4. 使用jquery.qrcode生成二维码(转)
  5. sublime 添加代码片段(snippets)
  6. Atitit.论垃圾文件的识别与清理 文档类型垃圾文件 与api概要设计pa6.doc
  7. .net导出Excel
  8. Response.Write详细介绍
  9. Java程序员从笨鸟到菜鸟之(一百零七)一步一步学习webservice(一)开篇
  10. jquery对象和Dom对象的不同