Spring 学习笔记之通过 Java 代码装配 Bean

虽然很多场景下可以使用组件扫描和自动装配来实现 Spring 的自动化配置,但有些时候自动化配置的方案是行不通的,因此需要明确配置 Spring。比如你想讲第三方库中的组件装配到你的应用中,在这种情况下,你必须要显式装配。在进行显式配置的时候,有两种方案,Java 和 XML。

下面介绍通过 Java 代码显式装配 Bean。

一、创建配置类

创建配置类的关键在于 @Configuration 注解,@Configuration 注解表明该类是一个配置类,该类包含了在 Spring 上下文中如何创建 Bean 的细节。

1
2
3
4
5
6
7
8
package cn.javacodes.spring.configuration;
import org.springframework.context.annotation.Configuration;
/**
* Created by Eric on 2016/10/16.
*/
@Configuration
public class CDPlayerConfig {
}

二、声明简单的 Bean

要在 JavaConfig 中声明 Bean,我们需要写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加 @Bean 注解。比如下面的代码声明了 CompactDisc Bean:

1
2
3
4
@Bean
public CompactDisc transfer(){
return new Transfer();
}

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

默认情况下,bean 的 ID 于带有 @Bean 注解方法的名称是一样的。在上面的例子中,bean 的名字将会是 “transfer”。如果你想为它设置一个不同的名字,可以通过 name 属性指定它的 ID:

1
2
3
4
@Bean(name = "transfer-cd")
public CompactDisc transfer(){
return new Transfer();
}

另外,方法中的方法体可以是任何你想创建 Bean 的逻辑,比如你想在一组 CD 中随机选取一个 CD 进行播放也是可以的。

三、借助 JavaConfig 实现注入

前面声明的 CompactDisc Bean 是非常简单的,因为它没有任何依赖,那么现在想要声明一个 CDPlayer Bean,它依赖于 CompactDisc。

(一)引用创建 Bean 的方法

1
2
3
4
@Bean
public CDPlayer cdPlayer(){
return new CDPlayer(transfer());
}

这里同样使用了 @Bean 注解,并在构造 CDPlayer 时将 CompactDisc 作为 CDPlayer 构造器的参数传入。

注意:这里虽然看起来是通过调用 transfer () 方法得到 CompactDisc,但由于 transfer 方法使用了 @Bean 注解,实际上 Spring 会拦截所有对它的调用,并确保直接返回该方法所创建的 Spring 上下文中的 bean,而不是每次都对其进行实际的调用。

比如说,假设你引入了另一个其他的 CDPlayer Bean,它和之前的那个 bean 完全一样。

1
2
3
4
5
6
7
8
@Bean
public CDPlayer cdPlayer(){
return new CDPlayer(transfer());
}
@Bean
public CDPlayer anotherCDPlayer(){
return new CDPlayer(transfer());
}

默认情况下,Spring 中的 bean 都是单例的,我们并没有必要为第二个 CDPlayer Bean 创建完全相同的 CompactDisc 实例。Spring 会拦截对 @Bean 注解标注方法的调用并确保返回的是 Spring 创建的 Bean。

(二)将依赖作为参数

可以看到通过引用创建 Bean 的方法来解决这个问题有些让人疑惑,下面这种方式看起来更为容易理解:

1
2
3
4
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
return new CDPlayer(compactDisc);
}

在这里,cdPlayer () 方法请求一个 CompactDisc 作为参数。当 Spring 调用 cdPlayer () 方法创建 bean 的时候,它会自动装配一个 CompactDisc 到配置方法中。这样方法体就可以在合适的位置使用它,通过这种方式可以避免明确的调用 @Bean 方法。

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

本例中使用了 CDPlayer 的构造器实现了 DI(依赖注入),但是完全可以使用其它风格的 DI,比如,你可以使用 setter 的方式进行注入。