这是我阅读Spring In Action的记录,如有理解错误的地方,欢迎大家指导。
装配Bean
如何实现Bean装配
Spring 从两个角度来实现自动化装配
组件扫描component scanning:Spring会自动发现应用上下文中创建的bean;
自动装配autowiring:Spring自动满足bean之间的依赖;
注解介绍
@Configuration和@ComponentScan
组件扫描不是默认开启的:@Configuration和@ComponentScan注解配合来开启组件扫描;
@ComponentScan:默认会扫描与配置类相同的包以及这个包下所有的子包;
指定扫描的包:@ComponentScan(basePackages = “com.spring.component”)
指定多个扫描的包:@ComponentScan(basePackages = {“com.spring.component”,“com.spring.service”})
指定某些类所在的包为基础扫描包:@ComponentScan(basePackageClasses = {SpringConfigDemo.class, SpringServiceDemo.class})
// 通过java代码定义了spring的装配规则
@Configuration
@ComponentScan //在spring中启动组件扫描,默认扫描与配置类相同的包以及这个包下的所有子包
public class CDPlayerConfig {
}
@Component
定义一个可装配的bean:@Component;
为bean命名:@Component(“sgtPeppers”)
@Component
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);
}
}
@Autowired
通过为bean添加注解实现自动装配;
通过构造器注入:
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
通过setter方法注入:
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
public void play() {
cd.play();
}
@Autowired
public void setCd(CompactDisc cd) {
this.cd = cd;
}
}
setter并不重要,可以通过其它名称的方法注入:
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
public void play() {
cd.play();
}
@Autowired
public void insertCd(CompactDisc cd) {
this.cd = cd;
}
}
没有找到要装配的bean会抛出异常,可以通过设置@Autowired(required = false)来避免;
通过Java代码装配Bean
如果要使用的Bean是一个第三方的jar包里面定义的,那个代码里面没有@Component注解,Spring不会自动创建这个实例,并且把它注册到Spring的应用上下文中去,因此,就不能用自动化装配的方案了。
注释掉@ComponentScan,Spring就不会去扫描其它带有@Component注解的Bean并初始化到Spring上下文中去了。这个时候需要使用@Bean注解来初始化Bean到Spring的上下文中去了。
@Configuration
//@ComponentScan
public class CDPlayerConfig {
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
}
public interface CompactDisc {
void play();
}
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);
}
}
还可以使用@Bean(name=“lonelyHeartClubBand”)来给这个Bean指定一个名字。
如果有一个对象依赖sgtPeppers对象,像下面这样:
public interface MediaPlayer {
void play();
}
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
就需要像下面这样来初始化该Bean了:
@Configuration
public class CDPlayerConfig {
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}
}
有一些值得注意的地方,sgtPeppers方法上面有@Bean注解,这将导致,Spring会拦截所有对它的调用,确保直接返回该方法创建的bean,而不是每次都对其进行实际的调用。
默认情况下,Spring中的bean都是单例的,这样每次返回的都是Spring所创建的bean。
本地运行使用的pom.xml和测试类的写法
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springdemo</groupId>
<artifactId>springdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springdemo</name>
<description>how to use spring</description>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- hibernate, ibatis, mybatis -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- 面向切面编程 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- 字节码增强 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- 自定义标签 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
</dependency>
<!-- <dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.19.0</version>
</dependency> -->
</dependencies>
</project>
测试类
package soundsystem;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) //测试的时候自动创建应用的上下文
@ContextConfiguration(classes=CDPlayerConfig.class) //从CDPlayerConfig类中加载
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Autowired
private CompactDisc sgtPeppers;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
@Test
public void play() {
//sgtPeppers.play();
}
}