Spring实战之二:装配Bean

2.1 Spring配置的可选方案

Spring提供了三种装配机制:

  1. 在XML中显式配置
  2. 在Java中显式配置
  3. 隐式的bean发现机制和自动装配

Best Practice:尽可能使用自动配置的机制,必须使用显式配置时,优先选择JavaConfig

2.2 自动化装配bean

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

  • 组件扫描:自动发现应用上下文创建的bean
  • 自动装配:自动满足bean之间的依赖

2.2.1 创建可被发现的bean

相关注解:

  • Component:表明该类为组件类,需要为该类创建bean
  • ComponentScan:默认会扫描与配置类相同的包及其子包
  • Runwith:junit的注解,和SpringJUnit4ClassRunner类一起,在测试开始时自动创建Spring的应用上下文
  • ContextConfiguration:告知去加载哪个配置类
  • Autowired:告诉Spring这里需要注入一个bean
  • Configuration:表明该类为配置类
  • Bean:告诉Spring该方法会返回一个对象,要把该对象注册到应用上下文中去

默认情况下并不启用组件扫描,所有我们还需显式配置一下。

2.2.2 为组件扫描的bean命名

如果不指定的话,Spring扫描到的bean的id为其类名,但第一字母小写,如果想给bean指定一个id,可以用一下方式:

@Component("beanName")

2.2.3 设置组件扫描的基础包

如果不指定,@ComponentScan会以配置类所在的包为基础包,我们可以显示地指定要扫描的基础包,特别是当我们想把所有配置类单独放置到一个包中时。可以用以下几种方式指定包名:

  • @CompenentScan("soundsystem")
  • @CompenentScan(basePackages = "soundsystem")
  • @CompenentScan(basePackages = {"soundsystem","video"})
  • @CompenentScan(basePackageClasses = {CDPlayer.class,DVDPlayer.class})

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

在满足依赖的过程中,Spring会在应用上下文寻找匹配某个bean需求的其他bean。通过@Autowired注解可以表明某个地方需要注入一个bean。Autowired注解可以放在成员变量,构造方法,setter,甚至是其他方法上,Spring会尝试满足方法参数上所声明的依赖。
如果没有bean匹配需求的话,会抛出异常,可以将注解的required属性设为false来避免异常的出现。多个bean满足需求时,也会抛出一个异常。
@Autowired约等于@Inject

通过Java代码装配bean

某些情况下无法使用自动扫描,比如要把第三方组件装配到应用中,此时可以采用显式装配方式,显式装配有两种方案:Java和XML。要注意,JavaConfig是配置代码,不应该包含任何业务逻辑,通常把JavaConfig放到单独的包里去。

2.3.1 创建配置类

创建配置类的关键在于为其添加@Configuration注解,该注解表明这是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。

2.3.2 声明简单的bean

要在JavaConfig中声明bean,需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加@Bean注解,告诉Spring该方法会返回一个对象,要把该对象注册到应用上下文中去,代码示例如下:

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

这种方式创建的bean默认的名字和方法名是一样的,可以显式地为bean指定名字:

@Bean(name="myBean")

借助JavaConfig实现注入

在JavaConfig中装配bean最简单的方式就是引用创建bean的方法,示例代码如下:

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

上述代码中,cdPlayer方法使用了@Bean注解,表明了该方法会创建一个bean实例并注册到应用上下文中,而创建CDPlayer对象时,需要为该对象注入一个CompactDisc类型的依赖,表面上,该依赖是通过调用sgtPeppers()方法得到的,但由于sgtPeppers()方法上添加了@Beanz注解,Spring会拦截所有对它的调用,并确保直接返回该方法创建个bean,而不是每次都对其进行实际调用。所有实际上cdPlayer所需的依赖是从应用上下文中得到的。默认情况下,Spring中的Bean都是单例的。通过调用方法来应用bean的方式有点让人困惑,还有一种更好的方式如下:

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

Spring使用该方法创建Bean是,会自动装配一个CompactDisc到配置方法中。这种方式通常是最佳选择,它不会要求其依赖的bean要在同一个配置类这种创建,甚至没有要求依赖的bean要在JavaConfig 中声明,它可以是通过组件扫描或是XML来进行配置的。
带有@Bean注解的方法的方法体中可以以任意方式实现bean的创建。

通过XML装配bean

Spring刚开始时就是使用XML作为主要的配置方式的。学习本部分内容主要是来帮助我们维护已有的XML配置,在完成新的Spring工作时,我们最好使用自动化配置和JavaConfig。

2.4.1 创建XML配置规范

beans元素是所有Spring配置文件的根元素。

声明一个简单的bean

bean元素和@Bean注解有点类似,如下通过bean元素来声明一个bean:

<bean class="soundsystem.SgtPeppersCD"></bean>

没有明确指定id时,这个bean会根据全限定类名来命名,如上述bean的id将会是:soundsystem.SgtPeppersCD#0。其中,#0是一个计数形式,用来区分相同类型的其他bean。如果再声明一个相同的bean,它的id将会是:soundsystem.SgtPeppersCD#1
我们通常还是要为bean指定id的,因为稍后要引用它的话得通过id来引用,以下方式更为规范:

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

但为了减少繁琐的配置,那些不需要通过id引用的bean就不用指定id了。
这种方式比起JavaConfig的缺点如下:

  • JavaConfig可以在方法体中以任意方式创建bean,而xml方式bean的创建无需我们负责
  • bean的类型以字符串的方式设置在class属性中,在编译时无法进行类型检查,如果重命名了类,就会报错

借助构造器注入初始化bean

在xml方式中,只有一种声明bean的方式,即使用bean元素并指定class属性,但在注入依赖时,会有多种配置方案。比如构造器注入就有两种方案:

  • constructor-arg元素
  • 使用Spring3.0引入的c命名空间

使用constructor-arg元素比较冗长,但功能比较c命名空间强大。

构造器注入bean引用

通过构造器的方法示例如下:

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

通过c命名空间的示例如下:

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

指定构造器的属性以c:开头,后面跟的是构造器参数名,最后的-ref表明正在装配的是一个bean的引用而不是一个字符串。上述代码还有以下两种表示方式:

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

将字面量注入到构造器中

以下为本节要使用到的实体类的代码:

package soundsystem;

public class BlankDiscCD implements CompactDisc {
    private String title ;
    private String artist ;

    public BlankDiscCD(String title, String artist) {
        this.title = title;
        this.artist = artist;
    }

    public void play() {
        System.out.println("Playing "+title + " by " + artist);
    }
}

可以看到上述实体类中的构造器的参数都是非引用类型,在xml配置该bean的方式如下:

    <bean id="blankCD" class="soundsystem.BlankDiscCD">
        <constructor-arg value="i am title"/>
        <constructor-arg value="i am artist"/>
    </bean>

使用c标签的方式如下:

    <bean id="blankCD2" class="soundsystem.BlankDiscCD" 
        c:_title="titleStr"
        c:_artist="artistName"
    />

装配集合

装配集合使用set或list元素,两种元素的作用是一样的,可以用来装配Set,List甚至是数组

2.4.4 设置属性

调用setter方法来设置属性的方式如下:

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

以上设置会在装配时调用CDPlayer的setCd方法把compactDisc注入进去。
与构造器的c标签类似,这里也可以使用p标签,对于p标签,在此就不再赘述,需要用到的时候翻阅书本或查找文档就可以。

2.5 导入和混合配置

2.5.1 在JavaConfig中引用XML配置

我们先看一下以下JavaConfig:

package soundsystem;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

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

}

在上述的JavaConfig中,我们使用Import注解引用了另一个JavaConfig,使用ImportResource引用了一个xml配置。

2.5.2 在XML配置中引用JavaConfig

我们先看一下以下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/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="soundsystem.CDPlayerConfig"/>  

    <import resource="cd-config.xml"/>

</beans>

在上述xml配置中,我们使用了bean元素来引入JavaConfig,使用import元素来引入其他xml配置

猜你喜欢

转载自blog.csdn.net/u012124304/article/details/77507994