《Spring in Action》4th Edition 学习笔记
Spring 注入 bean 可以有如下三种方式:
- 自动注入
- 显式注入(java 配置)
- 显式注入(xml 配置)
自动注入
自动注入主要使用如下的技术:
- Component scanning:Spring 自动发现需要在应用上下文中生成的 bean
- Autowiring:自动注入 bean 依赖
配置可被发现的 beans
使用 @Component
注解配置可被发现的 Bean,默认名称为类名(首字母小写)
package soundsystem;
import org.springframework.stereotype.Component;
@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);
}
}
配置 Bean 的名称:
@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
...
}
定义 Spring 注入配置类
使用 @Configuration
注解标明这是 spring 的配置类。使用 @ComponentScan
注解开启 spring component scanning。
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
@Component
注解默认会扫描配置类所在的包,也可以通过 basePackages
属性配置需要扫描的包。
@Configuration
@ComponentScan("soundsystem")//扫描 soundsystem 包
public class CDPlayerConfig {
}
// 或者使用 basePackages 属性
@Configuration
@ComponentScan(basePackages="soundsystem")
public class CDPlayerConfig {
}
// 配置多个包
@Configuration
@ComponentScan(basePackages={
"soundsystem", "video"})
public class CDPlayerConfig {
}
// 使用 class 或 interface 指定需要扫描的包
@Configuration
@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
public class CDPlayerConfig {
}
basePackages
:使用字符串配置,不那么类型安全basePackageClasses
:使用 java 配置,类型安全(对重构友好)
Note:当使用 basePackageClasses
的时候,可以在需要扫描的包中定义一个空的标签接口(empty marker interface),这样可实现与业务代码的分离。
自动注入依赖
使用 @Autowired
注解自动注入依赖。无论你将 @Autowired
注解放在 构造函数
, setter方法
还是 任意方法
上,Spring 都会尝试去自动注入定义在方法参数中的依赖。当且仅有一个匹配的 Bean 的时候,Spring 就会自动注入。当匹配多个 Bean 时,Spring 会抛出异常。你也可以通过设置 @Autowired
注解的 required
属性设置这个依赖是否为必须。
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
// 构造函数注入
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
// setter方法注入
@Autowired
public void setCompactDisc(CompactDisc cd) {
this.cd = cd;
}
// 任意方法注入
@Autowired
public void insertDisc(CompactDisc cd) {
this.cd = cd;
}
// 设置依赖可为null
// 当spring在容器中不能找到对应的依赖时,不会抛出异常
@Autowired(required=false)
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
显式注入(Java 配置)
Java 配置 VS XML 配置
- Java:更强大、类型安全、重构友好
- XML:更灵活
Note:使用 Java 配置时,应该将 JavaConfig 和业务代码分开,最好使用不同的包管理。因为 JavaConfig 毕竟是配置文件,所以不应该和业务逻辑代码混一块。
@Bean
注解声明 Bean
使用 @Bean
注解生成对象的方法,Spring 就会注册这个方法返回的对象到 Spring 应用上下文中。
默认注册的 Bean 的名称为方法名,也可以通过 @Bean
注解的 name
属性定义 Bean 名称。
package soundsystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
}
// 指定注册 bean 的名称
@Bean(name="lonelyHeartsClubBand")
public CompactDisc compactDisc() {
int choice = (int) Math.floor(Math.random() * 4);
if (choice == 0) {
return new SgtPeppers();
} else if (choice == 1) {
return new WhiteAlbum();
} else if (choice == 2) {
return new HardDaysNight();
} else {
return new Revolver();
}
}
如何在 JavaConfig 中声明依赖于其他 Bean 的 Bean?只需要在声明方法的参数中指定需要的依赖类型,Spring 会自动帮你注入。(无论该方法依赖的 Bean 是在 JavaConfig 中声明的,还是 Xml 配置中声明的)
// 构造器注入
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
// setter方法注入
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
CDPlayer cdPlayer = new CDPlayer(compactDisc);
cdPlayer.setCompactDisc(compactDisc);
return cdPlayer;
}
显式声明(XML 配置)
XML 作为 Spring 以前的配置方法被大量的使用,所以有必要学习如何通过 XML 配置 Spring。但是,当开始一个新的项目时,推荐使用 Java 配置。
创建 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
http://www.springframework.org/schema/context">
<!-- configuration details go here -->
</beans>
Note:可使用 Spring Tool Suite 自动生成 XML 配置文件
声明一个简单的 Bean
<bean id="compactDisc" class="soundsystem.SgtPeppers" />
<bean>
元素和 JavaConfig 中的 @Bean
注解含义相同。id
指定了 bean 的名称,class
指定了 bean 的类型。当 Spring 遇到 <bean>
元素时,它会调用 SgtPepers
的默认构造函数来创建 bean。
正因为 class
属性使用字面量,所以不能进行编译时检查,不过可以使用 IDE 来进行类型的检查。
很多时候,声明一个 bean,还需要初始化很多属性,那么如何使用 Spring 注