《Spring实战》第四版读书笔记 第二章 装配Bean

在Spring中,对象无需本身查找或建立与其所关联的其余对象。相反,容器负责把须要相互协做的对象引用赋予各个对象。java

建立应用对象之间协做关系的行为一般称为装配(wiring),这也是依赖注入的本质。spring

2.1 Spring配置的可选方案

Spring提供了三种主要的装配机制:数组

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

做者建议尽量的使用自动装配的机制。显式配置越少越好,当必需要显式配置bean的时候(好比,有些源码不是由你来维护的,而当你须要为这些代码配置bean的时候),推荐使用类型安全而且比XML更增强大的JavaConfig。最后,只有当你想要使用便利的XML命名空间,而且在JavaConfig中没有一样的实现是才应该使用XML。安全

2.2 自动化装配bean

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

  • 组件扫描(component scanning):Spring会自动发现应用上下文中所建立的bean;
  • 自动装配(autowiring):Spring自动知足bean之间的依赖。

2.2.1 建立可被发现的bean

在类上使用@Component注解,这个注解代表该类会做为组件类,并告知Spring要为这个类建立bean。测试

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

@Configuation
@ComponentScan
public class CDPlayerConfig {
}

若是没有其余配置,@ComponentScan默认会扫描与配置类相同的包。spa

若是想使用XML来启用组件扫描,可使用Spring context命名空间的context:component-scan元素。code

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

测试组件扫描代码:component

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerText {
    @Autowired
    private CompactDisc cd;
    
    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(cd)
    }
}

CDPlayerTest使用了Spring的SpringJUnit4ClassRunner,以便在测试开始的时候自动建立Spring的应用上下文。注解@ContextConfiguration会告诉它须要在CDPlayerConfig中加载配置。

2.2.2 为组件扫描的bean命名

在组件扫描中若是没有明确的设置ID,Spring会根据类名为其指定一个ID。这个bean所给定的ID是首字母变为小写的类名。

若是想为这个bean设置不一样的ID,须要将其做为值传递给@Component注解。

@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
}

另一种bean命名方式使用Java依赖注入规范中提供的@Named注解:

@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
}

Spring支持将@Named做为@Component注解的替代方案。二者之间由一些细微的差别,但在大多数场景中能够互换。

本书的做者更喜欢@Component。

2.2.3 设置组件扫描的基础包

若是没有为@ComponentScan设置属性,按照默认规则,它会以配置类所在的包做为基础包来扫描逐渐。

若是想扫描不一样的包,在@ComponentScan的value属性中指定包名便可。

@Configuraion
@ComponentScan("soundsystem")
public class CDPlayerConfig{
}

若是想更加清晰的代表所设置的是基础包,能够经过basePackages属性进行配置:

@Configuration
@ComponentScan(basePackages="soundsystem")
public class CDPlayerConfig{}

basePackages属性能够设置多个包,赋值一个数组便可:

@Configuration
@ComponentScan(basePackages={"soundsystem", "video"})
public class CDPlayerConfig { }

除了将包设置为简单的String类型外,@ComponentScan哈提供了另一种方法,将其指定为包中所包含的类或接口:

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

2.2.4 经过为bean添加注解实现自动装配

能够在构造器、setter方法、任何方法上使用@Autowired注解,Spring会尝试知足方法参数上所声明的依赖。假若有且只有一个bean匹配依赖需求,那么这个bean将会被装配进来。

若是没有匹配的bean,那么在应用上下文建立的时候会抛出异常。能够将@Autowired的required属性设置为false,此时Spring会尝试自动装配,可是若是没有匹配的bean的话该属性将会为null。

若是有多个bean都知足依赖关系,Spring将会抛出异常。

@Autowired是Spring特有的注解。可使用@Inject注解替代。

2.3 经过Java代码装配Bean

显式的装配方式有两种:Java和XML。

2.3.1 建立配置类

@Configuration注解代表这个类是一个配置类,该类应该包含在Spring应用上下文中如何建立bean的细节。

2.3.2 声明简单bean

要在JavaConfig中声明bean,须要编写一个方法,这个方法会建立所需类型的实例,而后给这个方法添加@Bean注解。

@Bean注解会告诉Spring这个方法将返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终产生bean实例的逻辑。

默认状况下,bean的ID与方法名一致。若是想为其设置一个不一样的名字,能够重命名该方法,也能够经过@Bean的name属性指定。

2.3.3 借助JavaConfig实现注入

在JavaConfig中装配bean的最简单方式就是引用建立bean的方法。在方法上添加了@Bean注解,Spring将会拦截全部对它的调用,并确保直接返回该方法所建立的bean,而不是每次都对其进行实际的调用。

经过调用方法引用bean的方式有点使人困惑。还有一种理解起来更简单的方式:

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

cdPlaye()方法请求一个CompactDisc做为参数,当Spring调用cdPlayer()建立CDPlayer bean的时候,它会自动装配一个CompactDisc到配置方法之中。

经过这种方式引用其余的bean一般是最佳的选择,由于它不会要求将CompactDisc声明到同一个配置类之中。在这里甚至没有要求CompactDisc必需要在JavaConfig中声明,实际上它能够经过组件扫描功能自动发现或者经过XML来进行配置。能够将配置分散到多个配置类、XML文件以及自动扫面和装配bean之中。

2.4 经过XML装配Bean

2.4.1 建立XML配置规范

在XML配置中,要建立一个XML文件,而且要以<beans>元素为根。

<?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.springframeword.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context">

        <!-- 配置详情 -->
</beans>

2.4.2 声明一个简单的<bean>

<bean>元素相似于JavaConfig中的@Bean注解。

若是没有给定ID,因此这个bean将会根据全限定类名来进行命名。例如“soundsystem.SgtPeppers#0“,其中“#0”是一个计数形式,用来区分相同类型的其余bean。

2.4.3 借助构造器注入初始化bean

构造器注入有两种基本的配置方案可供选择:

  • <constructon-arg>元素;
  • 使用Spring 3.0 所引入的c-命名空间。

构造器注入bean引用

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

c-命名空间的schema:

xmlns:c="http://www.springframework.org/schema/c"
<bean id="cdPlayer" class="soundsystem.CDPlayer" 
    c:cd-ref="compactDisc" />

属性以c:开头,也就是命名空间的前缀。接下来是要装配的构造器参数名,在此以后是-ref,这是一个命名约定,告诉Spring正在装配的是一个bean应用。

可使用参数在整个参数列表中的位置来替代参数名:

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

由于在XML中不容许数字做为属性的第一个字符,所以必需要添加一个下划线做为前缀。

若是只有一个参数,不用标示参数:

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

将字面量注入到构造器中

<bean id="compactDisc"
    class="soundsystem.BlankDisc">
    <constructor-arg value="sgt. Pepper" />
</bean>

依然使用<constructor-arg>元素进行注入,可是使用了value属性。

<bean id="compactDisc"
    class="soundsystem.BlankDisc"
    c:_title="sgt. Pepper"/>

使用c-命名空间装配字面量与装配引用的区别在于属性名中去掉了-ref后缀。

装配集合

<constructor-arg>能够将集合装配到构造器参数重,而c-命名空间不能。

可使用<null/>元素将null传递给构造器。

可使用<list>元素声明一个列表:

<constructor-arg>
    <list>
        <value>.....</value>
        <value>......</value>
    </list>
</constructor-arg>

<list>元素是<constructor-arg>的子元素,这代表一个包含值的列表将会传递到构造器中。其中<value>元素用来指定列表中的每一个元素。

与之相似,可使用<ref>元素代替<value>,实现bean引用列表的装配。

能够用相同的方式使用<set>元素。<set>和<list>元素的区别不大,不管在哪一种状况下,<set>或<list>均可以用来装配List、Set甚至是数组。

2.4.4 设置属性

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

Spring提供了p-命名空间做为<property>元素的替代方案。p-命名空间的schema:

xmlns:p="http://www.springframework.org/schema/p"

util-命名空间所提供的功能之一是util:list元素,它会建立一个列表的bean。

xmlns:util="http://www.springframework.org/schema/util"
<util:list id="trackList">
    <value>......</value>
    <value>.....</value>
</util:list>

下表展现了Spring util-命名空间中的元素

元素 描述
util:constant 引用某个类型的public static域,并将其暴露为bean
util:list 建立一个java.util.List类型的bean,其中包含值或引用
util:map 建立一个java.util.Map类型的bean,其中包含值或引用
util:properties 建立一个java.util.Propertie类型的bean
util:property-path 引用一个bean的属性(或内嵌属性),并将其暴露为bean
util:set 建立一个java.util.Set类型的bean,其中包含值或引用

2.5 导入和混合配置

2.5.1 在JavaConfig中引用XML配置

使用@Import注解引用其余JavaConfig配置,使用@ImportResource注解引入XML配置。

@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {
    
}

2.5.2 在XML配置中引用JavaConfig

在XML中可使用<import>元素来引用其余XML配置。

将JavaConfig做为bean使用<bean>元素导入XML配置文件。

相关文章
相关标签/搜索