本章内容
- 声明bean
- 构造器注入和Setter方法注入
- 装配bean
- 控制bean的创建和销毁
在Spring中,对象无需自己查找或创建与其所关联的其他对象,相反,容器负责把需要协作的对象引用赋予给各个对象,创建应用对象之间协作关系的行为我们称之为装配(waring),这也是DI(依赖注入)的本质
注意 DI是Spring最基本的要素,所以在开发基于Spring的应用时,你随时都在使用这些技术
Spring配置中最常见的三种方法
当描述Bean如何进行装配时,Spring具有很大的灵活性,它提供了三种主要的装配机制
1.在Xml中进行显性配置
2.在java中进行显性配置
3.隐式的bean发现机制和自动装配
至于选择哪种装配机制,Spring的装配风格是多样的,你可以自由组合,但是应当尽可能的选择自动配置的机制,显式配置越少越好,当你需要显式配置bean的时候(比如这些代码不是由你维护,而你需要装配bean的时候),应当用类型安全并且比Xml更强大的JavaConfig,最后只有当你想要使用便利的Xml并且Java Config没有相关的实现时,才使用Xml
自动化装配bean(便利性最强)
Spring从两个角度来实现自动化装配
- 自动化扫描(componment Scanning):Spring会自动发现应用上下文中所创建的bean
- 自动配装(autowiring):Spring自动满足bean之间的依赖
组件扫描和自动装配组合在一起就能发挥强大的威力,他们能将你的显式配置降低到最少
创建可以被发现的bean
例子:这里有个cd播放器类,你必须将cd注入
package soundsystem;
public interface CompactDisc {
// 定义cd的接口概念
void play();
}
在这里,接口的内容不重要,重要的是你即将其定义为了接口,作为接口,他定义了CD播放器对一盘CD能做的操作,他将cd播放器与 cd的耦合度降到了最小的程度
我们去创建一个CompactDisc的具体实现,事实上可以有多个实现,目前我们只创建这一个,也就是下面的sgtPeppers类
带有@Component注解的CompactDisc实现类sgtPeppers
package soundsystem;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc{
private String title = "small love song";
private String artist = "jim";
@Override
public void play() {
System.out.println("playing"+title+"by"+artist);
}
}
和CompactDisc接口一样,sgtPeppers的具体内容不重要,重要的是sgtPeppers类上使用了@Component注解,这个简单的注解会表明该类会成为组件类,并告知Spring要为这个类创建bean
但是,组件扫描默认是不启用的,我们还需要显式的配置下Spring,从而命令他去寻找带有@Component注解的类,并为其创建bean,下面的程序完成了这项简单的配置
@ComponentScan开启了组件扫描
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
//@ComponentScan注解开启了组件扫描
@ComponentScan
public class CDPlayerConfig {
}
类CDPlayerConfig通过java代码定义了Spring的装配规则,稍后再详细了解基于Java的详细配置,现在我们主要观察CDPlayerConfig类并没有显式的声明任何bean,只不过它使用了@ComponentScan注解,这个注解能够在Spring中启用组件扫描
如果没有其他配置的话,@ComponentScan会首先扫描与配置类相同的包,因为CDPlayerConfig位于soundsystem包中,因此Spring将会扫描这个包与他之下的所有子包,找到带有@Conponent注解的类,这样就能发现CompactDisc,并且会在Spring中自动为其创建一个bean
通过Xml启用组件扫描
comtext:compoenet-scan会有与@CompoenetScan对应的属性和子元素
目前为止,创建了两个类,我们就已将能够完成组件测试了
看下面的测试实例(CompactDisc),我们创建一个简单的Junit测试,他会创建Spring上下文,并判断CompactDisc是不是真的被创建出来了
package soundsystem;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.Assert.assertNotNull;
//使用Spring的SpringJunit4ClassRunner,以便在测试开始的时候创建Spring的应用上下文
@RunWith(SpringJunit4ClassRunner.class)
//在ContextConfiguration告诉他需要在CDPlayConfig中加载配置
//因为CDPlayerConfig类中包含@ComponentScan,因此最终的应用上下文中应该包含CompactDisc bean
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayTest {
// @Autowired注解,以便将CompactDisc bean注入到测试代码中
@Autowired
private CompactDisc cd;
@Test
//简单的测试方法断言cd的属性不为null
// (不为null就意味着Spring能够发现CompactDisc类,自动在Spring上下文中将其创建为bean并将其注入到测试代码中)
public void sdShowNotBeNull(){
assertNotNull(cd);
}
}
因为Spring实战这本书没有(maven)pom.xml依赖详情,所以程序会出现错误,可以参照我的pom.xml,就可以完成测试
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3.RC2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-library -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
如果成功运行,测试区会显示绿色,至此为止,你已经写下一个简单的扫描组件测试类,
下面,我们将深入探讨@ComponentScan和@Component
为组件扫描的bean命名
Sprng应用上下文中的所有bean都会给定一个ID,之前的例子中,虽然没有给SgtPeppers bean设置ID,但Spring会根据类名为其指定一个ID,具体来说,这个bean所给定的ID为sgtPeppers,也就是将类名的第一个字母变小写.
-
如果想为这个bean设置不同的ID,就要你所要期望的ID作为值传递给@Component注解,比如想将这个bean表示为lonelyHeartsClub
@Component(“lonelyHeartsClub”)
//就应该在SgtPeppers类的@Component配置为如下所示
public class SgtPeppers implements C