Spring-装配 Bean

装配:创建应用对象之间协作关系的行为。

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

  • 在 XML 中进行显式配置
  • 在 Java 中进行显式配置
  • 隐式的 bean 发现机制和自动装配 装配方案选择:尽可能地使用自动配置的机制;当必须要显式配置 bean 的时候,推荐使用类型安全并且比 XML 更加强大的 JavaConfig;只有当想要利用便利的 XML 命名空间,并且在 JavaConfig 中没有同样的实现时,才应该使用 XML。

自动化装配 Bean

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

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

实现流程:

  • 创建类并将其标记为使用 Spring 容器管理。示例代码:
1
2
3
4
5
package wiki.hlj.ch2;

public interface Sport {
void run();
}
1
2
3
4
5
6
7
8
9
10
11
12
package wiki.hlj.ch2;
import org.springframework.stereotype.Component;

@Component
public class Hurdle implements Sport {
public void run() {
int amount = 10;
String name = "Bill";
System.out.println(name + " crossed " + amount + " hurdles in a minute.");
}

}
  • 启用组件扫描,可以使用 @ComponentScan 注解或者使用 XML (<context:component-scan>)。示例代码:
1
2
3
4
5
6
7
8
9
10
11
   package wiki.hlj.ch2;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

// Configuration 注解表明这个类是一个配置类,
// 该类应该包含在 Spring 应用上下文中如何创建 bean 的细节
@Configuration
@ComponentScan(basePackages = {"wiki.hlj.ch2"})
public class SportConfig {
}
  • 测试。示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package wiki.hlj.ch2.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import wiki.hlj.ch2.Sport;
import wiki.hlj.ch2.SportConfig;

@RunWith(SpringJUnit4ClassRunner.class)// 自动创建 Spring 的应用上下文
@ContextConfiguration(classes = SportConfig.class)
public class SportTest {

@Autowired
private Sport sport;

@Test
public void testRun() {
sport.run();
}

}

也可以使用 Java 依赖注入规范中所提供的 @Named 注解来为 bean 设置 ID,但这种方式不推荐
@Inject 注解来源于 Java 依赖注入规范,在大多数场景下,它可以和 @Autowired 互相替换,并
@Autowired 注解可以用在类的任何方法上

通过 Java 代码装配 bean

JavaConfig 是配置代码,它不应该包含任何业务逻辑,也不应该侵入到业务逻辑代码之中,通常会将 JavaConfig 放到单独的包中,使它与其他的应用程序逻辑分离开来。
实现流程:创建配置类 -> 声明简单的 bean -> 借助 JavaConfig 实现注入
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package wiki.hlj.ch2;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CDPlayerConfig {

// @Bean 注解会告诉 Spring 这个方法会返回一个对象,
// 该对象要注册为 Spring 应用上下文中的 bean
@Bean(name = "sgtPeppers")
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}

// sgtPeppers() 方法添加了 @Bean 注解,Spring 将会拦截所有对它的调用,
// 并确保直接返回该方法所创建的 bean,而不是每次都对其进行实际的调用
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}

// 默认情况下,Spring 中的 bean 都是单例的
@Bean
public CDPlayer anotherCdPlayer() {
return new CDPlayer(sgtPeppers());
}

// 通过这种方式引用其他的 bean 通常是最佳的选择,
// 因为它不会要求 CompactDisc 声明到同一个配置类之中。
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
}
1
2
3
4
5
6
7
package wiki.hlj.ch2;

public interface MediaPlayer {

void play();

}
1
2
3
4
5
6
7
package wiki.hlj.ch2;

public interface CompactDisc {

void play();

}
1
2
3
4
5
6
7
8
9
10
11
12
13
package wiki.hlj.ch2;


public class SgtPeppers implements CompactDisc {

private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";

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

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package wiki.hlj.ch2;
import org.springframework.beans.factory.annotation.Autowired;

public class CDPlayer implements MediaPlayer {
private CompactDisc cd;

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

public void play() {
cd.play();
}

}

通过 XML 装配 bean

使用 bean 元素,示例<bean id="sayHello" class="wiki.hlj.ch1.SayHello" />

借助构造器注入初始化 bean,两种方案:

  • <constructor-arg> 元素

  • 使用 Spring 3.0 所引入的 c- 命名空间(目前,使用 c- 命名空间无法实现装配集合的功能)

设置属性:
<property> 元素;p- 命名空间

混合配置

@Import 注解

假设 AConfig 中装载了类 A,BConfig 中装载了类 B,同时类 B 依赖于类 A,则可在类 B 类声明上方使用注解 @Import(AConfig.class);或者创建一个更高级别的 SummaryConfig ,在这个类中使用 @Import 将两个配置组合在一起:@Import(AConfig.lass, BConfig.class)

@ImportResource 注解

通过它可实现在 JavaConfig 中引用基于 XML 的配置
在 XML 中,可以使用 <import> 元素来拆分 XML 配置,实现在一个 XML 配置中引用另一个 XML 配置


Spring-装配 Bean
https://blog.yohlj.cn/posts/1ca92520/
作者
Enoch
发布于
2017年12月16日
许可协议