1. Spring配置的可选方案

  • 在XML中进行显式配置;
  • 在Java中进行显式配置;
  • 隐式的bean发现机制和自动装配。

2. 自动化装配bean

Spring从两个角度来实现自动化装配:

组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。

自动装配(autowiring):Spring自动满足bean之间的依赖。

2.1 创建可被发现的bean

使用了@Component注解。这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。

组件扫描默认是不启用的。我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。

启用组件扫描

  • 基于Java @ComponentScan注解启用了组件扫描
@Configuration
@ComponentScan(basePackages="soundsystem","video")
public class CDPlayerConfig {
}

如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包。(通过一个空标记接口(remark interface)来这这个工作,是一个很好的实践。)

2.2 设置组件扫描的基础包

上面的例子中,所设置的基础包是以String类型表示的。我认为这是可以的,但这种方法是类型不安全(not type-safe)的。除了将包设置为简单的String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所包含的类或接口:

@Configuration
@ComponentScan(basePackageClasses = {CDPlayer.class})
public class CDPlayerConfig {
}

basePackages属性被替换成了basePackageClasses。同时,我们不是再使用String类型的名称来指定包,为basePackageClasses属性所设置的数组中包含了类。这些类所在的包将会作为组件扫描的基础包。

  • 通过XML启用组件扫描
<context:component-scan base-package="soundsystem" />

2.3 通过为bean添加注解实现自动装配

为了声明要进行自动装配,我们可以借助Spring的@Autowired注解.

@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上。

@Autowired
public void setCompactDisc(CompactDisc cd) {
this.cd=cd;
}

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属

性设置为false:

@Autowired(required = false)
public CDPlayer(CompactDisc cd){
this.cd=cd;
}

3. 通过Java代码装配bean

你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了。 在这种情况下,你必须要采用显式装配的方式。在进行显式配置的时候,有两种可选方案:Java和XML。

JavaConfig是配置代码。这意味着它不应该包含任何业务逻辑,JavaConfig也不应该侵入到业务逻辑代码之中。尽管不是必须的,但通常会将JavaConfig放到单独的包中,使它与其他的应用程序逻辑分离开来,这样对于它的意图就不会产生困惑了。

  • 声明简单的bean
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
  • 借助JavaConfig实现注入
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}

通过这种方式引用其他的bean通常是最佳的选择,因为它不会要求将CompactDisc声明到同一个配置类之中。在这里甚至没有要求CompactDisc必须要在JavaConfig中声明,实际上它可以通过组件扫描功能自动发现或者通过XML来进行配置。

  • 使用方法替代构造器的注入

    需要提醒的是,我们在这里使用CDPlayer的构造器实现了DI功能,但是我们完全可以采用其他风格的DI配置。比如说,如果你想通过Setter方法注入CompactDisc的话,那么代码看起来应该是这样的:
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
CDPlayer cdPlayer = new CDPlayer(compactDisc);
cdPlayer.setCompactDisc(compactDisc);
return cdPlayer;
}

4. 通过XML装配bean

  • 声明一个简单的<bean>
<bean class="soundsystem.SgtPeppers"/>
  • 借助构造器注入初始化bean
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="compactDisc"/>
</bean>
  • 使用方法替代构造器的注入
<bean id="cdPlayer"  class="soundsystem.CDPlayer">
<property name="compactDisc" ref="compactDisc"/>
</bean>

<property>元素为属性的Setter方法所提供的功能与<constructor-arg>元素为构造器所提供的功能是一样的。

  • 将字面量注入到属性中

    有Java对象如下:
public class BlankDisc implements CompactDisc {

  private String title;
private String artist;
private List<String> tracks; public BlankDisc(String title, String artist, List<String> tracks) {
this.title = title;
this.artist = artist;
this.tracks = tracks;
} public void play() {
System.out.println("Playing " + title + " by " + artist);
for (String track : tracks) {
System.out.println("-Track: " + track);
}
} }

可用以下xml将字面值(String、List<String>)注入到属性中:

<bean id="compactDisc"
class="soundsystem.properties.BlankDisc">
<property name="title" value="Sgt. Pepper's Lonely Hearts Club Band" />
<property name="artist" value="The Beatles" />
<property name="tracks">
<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>
<value>She's Leaving Home</value>
<value>Being for the Benefit of Mr. Kite!</value>
<value>Within You Without You</value>
<value>When I'm Sixty-Four</value>
<value>Lovely Rita</value>
<value>Good Morning Good Morning</value>
<value>Sgt. Pepper's Lonely Hearts Club Band (Reprise)</value>
<value>A Day in the Life</value>
</list>
</property>
</bean>

5. 导入和混合配置

5.1 在JavaConfig中引用XML配置

  • Java配置
@Configuration
public class CDPlayerConfig { @Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
} }
  • XML配置
<bean id="compactDisc"
class="soundsystem.BlankDisc"
c:_0="Sgt. Pepper's Lonely Hearts Club Band"
c:_1="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>

以上xml配置中使用了c命名空间,这里_0,_1相当与第一个参数和第二个参数。

  • 在Java配置中引入XML配置

    两个bean——配置在JavaConfig中的CDPlayer以及配置在XML中BlankDisc——都会被加载到Spring容器之中。代码如下:
@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig { }

@Import将两个配置类组合在一起;

@ImportResource可在JavaConfig中引入XML配置;

以上代码是利用一个新的Java配置类,引入了已有的Java配置类以及XML配置文件。当然也可以在已有的Java配置类中直接引入XML配置文件。

5.2 在XML配置中引用JavaConfig

  • Java配置
@Configuration
public class CDConfig {
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
}
  • XML配置
<bean id="cdPlayer"
class="soundsystem.CDPlayer"
c:cd-ref="compactDisc" />
  • 在XML配置中引入Java配置
<bean class="soundsystem.CDConfig" />

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

以上代码是在已有的XML配置文件中引入Java配置类,当然可以建立一个新的XML引入已有的XML配置文件和已有的Java配置类,如:

<bean class="soundsystem.CDConfig"/>
<import resource="cdplayer-config.xml"/>

XML配置文件应用已有XML配置文件使用<import resource>标签。

注意

不管使用JavaConfig还是使用XML进行装配,我通常都会创建一个根配置(root configuration),也就是这里展现的这样,这个配置会将两个或更多的装配类和/或XML文件组合起来。我也会在根配置中启用组件扫描(通过<context:component-scan>或@ComponentScan)。

Spring 3的一些内容

1、装配wiring,即创建应用对象之间的协作关系的行为,者也是依赖注入的本质。

2、创建Spring配置

从Sring3.0开始,Spring容器提供了两种配置Bean的方式:

XML文件配置方式
基于Java注解的配置方式

3、典型的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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

beans命名空间不是唯一的Spring命名空间,Spring核心框架自带了10个命名空间配置,如下:



4、当Spring容器加载Bean时,Spring使用反射来创建Bean。

5、覆盖Spring默认的单例配置:Spring Bean默认都是单例,但有时我们每次都需要获得唯一的Bean实例,比如每个人的门票要唯一:

我们只需要配置Bean的scope属性为prototype即可:

1



Spring提供的作用域选项:

6、初始化和销毁Bean

Auditorium(舞台)要保证做的最先和最后两件事情:

开灯,关灯。



需要在Bean中使用init-method和destory-method属性:



当有很多上下文定义的Bean有相同名字的初始化方法和销毁方法时,可以直接在上层beans元素中声明default-init-method和default-destory-method属性,从而避免每一个都要设置一遍的问题。

最小化Spring XML配置——

Bean的自动装配(autowiring);

Bean的自动检测(autodiscovery);

一、自动装配Bean属性

1、 4种类型的自动装配

byName——把与Bean的属性具有相同名字(或ID)的其他Bean自动装配到Bean的对应属性中,名字不匹配则不装配;

byType——把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中,类型不匹配则不装配;

constructor——把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中;

autodetect——首先尝试使用constructor自动装配,若失败,再尝试使用byType进行自动装配。

2、byName

原来的装配是这样的:





当bean的id属性和property属性的name一致时,通过配置autowire属性皆可以自动装配instrument了,修改后的文件如下:



3、byType自动装配

byType自动装配的工作方式类似于byName,只不过不再是匹配属性的名字而是检查属性的类型。

若Instrument类型有多个Bean,Spring就会抛出异常,为解决这个为,需要标识首选的Bean或者取消某个Bean的自动装配候选资格:

首选Bean

设置Bean的primary属性为true。但是不幸的是所有的bean的默认primary都是true,因此只能将非首选的Bean的primary属性设置为false:



取消Bean候选资格

排除某些Bean是,可设置这些Bean的autowire-candidate属性为false:



4、constructor自动装配

通过构造器注入来配置Bean,我们可以移除元素,由Spring在应用上下文中自动选择Bean注入到构造器入参中:



与byType一样,当发现多个Bean匹配某个构造器入参时,Spring依旧报出异常。

5、最佳自动装配



首选constructor自动装配,若没有发现与构造器相匹配的Bean时,Spring将尝试使用byType自动装配。

6、默认自动装配

当需要为上下文中的每一个Bean配置相同的上述自动装配autowire属性,可以在根目录增加一个default-autowire属性:



该属性默认none,标示所有Bean都不使用自动装配,除非Bean自己配置了autowire属性。

另外,种配置的autowire属性可以覆盖根元素的默认自动装配策略——混合策略。

混合策略对构造器有所限制:不能混合使用constructor自动装配策略和元素。

二、使用注解装配

注解方式允许更细粒度的自动装配,可以选择性地标注某一个属性来对其应用自动装配。

Spring容器默认禁止注解装配,最简单的启用方式是使用Spring的context命名空间配置中的元素。



注解,可以为Spring属性、方法和构造器进行自动装配,因此要写在这些的上方一行。

1、@Autowired

对属性的setter方法进行标注:



Spring会尝试对该方法执行byType自动装配。

除了setter方法,@Autowired可以标注需要自动装配Bean引用的任何方法、构造器。





甚至可以使用@Autowired直接标注属性,并删除setter方法:



但是,简单的@Autowired标注有两种麻烦——没有bean或者多个bean:

没有bean

当属性是可选的,而bean不存在时,可以使用required属性:

@Autowired(required=false)

多个bean【限定歧义性的依赖】

为帮助@Autowired鉴别哪一个Bean才是我们想要的,可配合使用Spring的@Qualifier注解,该注解可以包含一个字符串作为Bean的标识(标识不一定是id)。

如将一个id为guitar的乐器装配到instrument属性中:



注意,上述的guitar可以在xml中对的id属性设置;

另外,可以不用id属性,而是在中以qualifier子元素(子元素vs属性)中写明,或者在Guitar类上标注:





若是Qualifier含义不是那么明确或者范围过大,可以自定义Qualifier接口,以代替Qualifier:



2、借助@Inject实现基于标准的自动装配

JCP(Java Community Process)发布Java依赖注入规范——JSR-330,@Inject注解是JSR-330的核心部件。

》note: JDK中并没有JSR-330的实现,需要下载响应的jar依赖包http://mvnrepository.com/artifact/javax.inject/javax.inject

@Inject

和@Autowired一样,@Inject可以自动装配属性、方法和构造器,但是没有required属性,即@Inject注解所标注的依赖关系必须存在,否则会报出异常。

与@Autowired对应的@Qualifier类似,@Inject对应@Name注解。

@Inject本身也有@Qualifier注解,但是不推荐使用,而是推荐自定义限定器注解。

3、在注解中使用表达式

String类型以及基本类型的属性,可以直接通过@Value的方式填入值。但是这相当于硬编码,与直接写在代码中没多大区别,因此不推荐使用,如一首歌名Eruption:



但是@Value可以使用SpEL表达式,获取系统属性,功能强大:

三、自动检测Bean

= +自动检测和定义Bean。

自动检测可以免去的定义,是的Spring应用中的大多数甚至所有Bean实现定义【厉害啊】和装配。

元素即负责Spring的自动检测Bean和定义Bean。

【vs ,该元素有助于消除Spring配置中的和元素,但是依旧需要显示定义】

使用代替 元素:



那么,哪些类需要注册为Spring的Bean呢?

1、为自动检测标注Bean

默认地,查找使用“构造型(stereotype)”注解所标注的类,这些特殊的注解如下:



如,对一个类注解@Component:



那么Spring扫描到Guitar,会自动将它注册为Spring Bean,该Bean的ID默认为无限定类名(何为无限定?)——guitar。

2、过滤组件扫描

通过为配置和子元素,我们可以随意调整扫描行为。如自动注册所有的Instrument实现类:



的type和expression属性一起协作来定义组件扫描策略。



不过,默认的基于注解的过滤策略是最经常用的。

四、使用Spring基于Java的配置

1、创建基于Java的配置

Spring的Java配置可以不用XML就可以编写大多数的Spring配置,但是还是需要极少量的XML来启动Java配置。就是说,XML总要有的。

Spring在base-package指定的包内查找使用@Configuration注解所标注的所有类。

2、定义一个配置类

使用@Configuration注解的Java类,就等价于XML配置中的元素,可以在改类内部定义@Bean方法了。



声明的方法示例如下,将得到ID为方法名的Bean:



优点:Spring的基于Java的配置中,并没有String属性,Bean的ID和类型都被是否方法签名的一部分,所以可以进行编译期检查来确保Bean的类型是合法类型,并且Bean的ID是唯一的。

vs XML配置:Bean的类型和ID都是由String属性标示的,String标识符的缺点是它们无法进行编译期检查,如果重命名了Juggler类,或许会忘记修改相应的XML配置!

智能:其他Bean的声明调用另一个Bean时,Spring都会拦截该方法的调用,并尝试在应用上下文中查找该Bean,而不是让方法创建一个新的实例。

源码

自动配置:https://github.com/myitroad/spring-in-action-4/tree/master/Chapter_02/stereo-autoconfig

Java配置:https://github.com/myitroad/spring-in-action-4/tree/master/Chapter_02/stereo-javaconfig

XML配置:https://github.com/myitroad/spring-in-action-4/tree/master/Chapter_02/stereo-xmlconfig

混合配置:https://github.com/myitroad/spring-in-action-4/tree/master/Chapter_02/stereo-mixedconfig

第02章-装配Bean的更多相关文章

  1. 第2章—装配Bean—通过java代码装配bean

    通过java代码装配bean ​ 在进行显式装配的时候,有两种选型方案:java和XML配置,这里先介绍java的配置方式. 2.3.1创建配置类 先复习下上一章的配置内容: @Configurati ...

  2. SpringInAction读书笔记--第2章装配Bean

    实现一个业务需要多个组件相互协作,创建组件之间关联关系的传统方法通常会导致结构复杂的代码,这些代码很难被复用和单元测试.在Spring中,对象不需要自己寻找或创建与其所关联的其它对象,Spring容器 ...

  3. Spring in Action --- 第二章 装配Bean

    Spirng配置的可选方案 在XML中进行显示配置 在Java中进行显示配置 隐式的bean发现机制和自动装配 bean装配 1. 在希望被扫描到的类上加注解 @Component 2. 基于不同的配 ...

  4. 第2章—装配Bean—通过XML装配Bean

    通过XML装配Bean ​ 尽管我们在生成Bean的过程中可以用到很多方法,但我们依然需要Spring的XML配置来完善更多的需求,下面就来介绍下XML装配Bean的过程是怎样的. 3.1创建XML配 ...

  5. 第2章—装配Bean—自动化装配Bean

    自动化装配Bean 2.1.Spring配置可选方案 ​ 装配是依赖注入DI的本质,Spring提供了以下三种注入的装配机制: 在XMl中进行显式配置 在java中进行显式配置 隐式的Bean发现机制 ...

  6. 第02章 IOC和bean的配置

    第02章 IOC容器和Bean的配置 1.IOC和DI ①IOC(Inversion of Control):反转控制. 在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资 ...

  7. #Spring实战第二章学习笔记————装配Bean

    Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...

  8. Spring入门篇——第4章 Spring Bean装配(下)

    第4章 Spring Bean装配(下) 介绍Bean的注解实现,Autowired注解说明,基于java的容器注解说明,以及Spring对JSR支持的说明 4-1 Spring Bean装配之Bea ...

  9. Spring入门篇——第3章 Spring Bean装配(上)

    第3章 Spring Bean装配(上) 介绍Bean的作用域.生命周期.Aware接口.自动装配和Resource等内容. 3-1 Spring Bean装配之Bean的配置项及作用域 从上至下依次 ...

随机推荐

  1. nginx 限制

    在nginx.conf里的http{}里添加: http{ limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $s ...

  2. 【转】学习使用Jmeter做压力测试(一)--压力测试基本概念

    一.性能测试的概念 性能测试是通过自动化的测试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测试,两者可以结合进行. 通过负载测试,确定在各种工作负载下 ...

  3. java内存基础(一)

    博客园 闪存 首页 新随笔 联系 管理 订阅 随笔- 35  文章- 0  评论- 29  关于Java 数组内存分配一点认识  //总结:[ 数组引用变量存储在栈内存中,数组对象存储在堆内存当中.数 ...

  4. Tarjan模版(链式向前星表示方法)

    这道模版用到了链式向前星表示法: struct node { int v,next; }edge[]; void add(int x,int y) { edge[++cnt].next=heads[x ...

  5. AngularJS:过滤器

    ylbtech-AngularJS:过滤器 1.返回顶部 1. AngularJS 过滤器 过滤器可以使用一个管道字符(|)添加到表达式和指令中. AngularJS 过滤器 AngularJS 过滤 ...

  6. windows服务器审核失败消息:事件ID: 861 进程标识符:904

    事件ID: 861   进程标识符:904 排查方法: win+R键调出运行窗口, 输入cmd 输入tasklist  /SVC /FI “PID eq 904” 查找进程号904对应的是不是dhcp ...

  7. 关系数据库SQL复习

    1.1 SQL的概述 SQL(Structured Query Language)结构化查询语言,是关系数据库的标准语言 SQL是一个通用的.功能极强的关系数据库语言 1.2 SQL的特点 1. 综合 ...

  8. springboot成神之——拦截器

    本文介绍spring boot拦截器 创建拦截器类LogInterceptor.java 创建拦截器类OldLoginInterceptor.java 拦截器配置类WebMvcConfig.java ...

  9. Storm集群详细部署

    1.安装zookeeper 3.1下载zookeeper安装包, 建议下载3.4.5及以上的版本 http://www.apache.org/dyn/closer.cgi/zookeeper/ 3.2 ...

  10. Delphi Help

    http://docwiki.embarcadero.com/CodeExamples/Seattle/en/Category:Content_by_Version