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将字面值(StringList<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. weblogic控制台的启动与禁用

    在一些安全漏洞扫描中,经常会扫描发现,使用weblogic管理控制台,会有个中危的漏洞. http://192.168.10.46:7001/console/login/LoginForm.jsp W ...

  2. 洛谷 4106 / bzoj 3614 [HEOI2014]逻辑翻译——思路+类似FWT

    题目:https://www.luogu.org/problemnew/show/P4106 https://www.lydsy.com/JudgeOnline/problem.php?id=3614 ...

  3. Swift app中的Crash捕获与处理

    1. 为什么会Crash 常见的Crash原因有:访问已经被释放的内存,数组越界,使用!解包值为nil的变量.当遇到这些情况时,说明应用已经遇到了很严重的非预期错误,无法再继续运行.操作系统检测到这些 ...

  4. PHP 16 个编程法则

    HP是最好的编程语言.对于PHP开发者来说,掌握一些编程法则是十分重要的.而在PHP中,以双下划线(__)开头的方法称为魔术方法,它们扮演着非常重要的角色. 常用的魔术方法包括: -__constru ...

  5. phantomjs 安装和试用

    准备学习casperjs, 发现官网上说  it’s an extremely useful companion to PhantomJS, 所以决定下把它下来试试.下载安装(win7)没什么可说的, ...

  6. NoSuchBeanDefinitionException: No bean named 'shiroFilter' is defined

    以前运行正常的项目,过了一段时间再运行时出问题,打开链接无反应,无法访问Tomcat,空白页面. 经检查发现,在Tomcat log中有报错: NoSuchBeanDefinitionExceptio ...

  7. WP10通过StreamSocket连接C++服务器

    注:当服务端和手机模拟器运行在一台机器时,会有奇怪错误.将服务端放在其它机器上更改客户端连接地址,运行正常.或者直接用本机modern调试也可以. 实例化一个对象 StreamSocket _clie ...

  8. 分布式爬虫搭建系列 之二-----神器PyCharm的安装

    这里我们使用PyCharm作为开发工具,以下过程摘抄于:http://blog.csdn.net/qq_29883591/article/details/52664478  作者:陌上行走 Pytho ...

  9. VS2010调用halcon的时候出现试图加载格式不正确的程序(this.hWindowControl1 = new HalconDotNet.HWindowControl();)

    [重要错误修改] /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容. /// </summary> private v ...

  10. leetcode804

    int uniqueMorseRepresentations(vector<string>& words) { map<char, string> st; st.ins ...