《Spring 实战》 读书笔记 第二章
Spring配置的可选方案
- 隐式的bean发现机制和自动装配(本章)
- 在Java中进行显示配置
- 在XML中进行显示配置
尽可能地使用自动配置的机制。显示配置越少越好(有些源码不是你来维护的,而当你需要为这些代码配置bean的时候,需要显示配置bean)。推荐使用类型安全并且比xml更加强大的JavaConfig。最后,只有当你想要使用便利的xml命名空间,并且在JavaConfig中没有同样的实现时,才使用xml。
自动化装配Bean
Spring从两个角度来实现自动化装配
- 组件扫描:Spring 会自动发现应用上下文所创建的bean
- 自动装配:Spring自动满足bean之间的依赖
组件扫描和自动装配组合在一起就能发挥强大的威力,能够将你的显示配置降低到最少。
创建可被发现的bean
package com.loveqrc;
public interface CompactDisc {
void play();
}
package com.loveqrc;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc {
String author = "梁静茹";
String title = "Today";
@Override
public void play() {
System.out.println("Playing" + title + "by" + author);
}
}
@Component表明该类会作为组件类,并且告知Spring要为这个类创建bean
但是组件扫描默认是不启动的,需要显示配置Spring。从而去寻找@Component组件,并为其创建bean。
package com.loveqrc;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
@ComponentScan注解启用组件扫描,如果不配置@ComponentScan的话,默认会扫描和配置类相同的包,因为CDPlayerConfig 位于com.loveqrc包下,因此Spring将会扫描这个包以及这个包下的所有子包,查找带有@Component注解的类,并且其创建一个bean。
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
CDPlayerTest 使用了Spring的SpringJUnit4ClassRunner,以便在测试开始的时候自动创建Spring的应用上下文,@ContextConfiguration会告诉它需要在CDPlayerConfig中加载配置,因为CDPlayerConfig包含@ComponentScan,最终应用上下文应该包含CompactDisc Bean。@Autowired将CompactDisc Bean注入到代码中。
上面的代码将通过测试。
为组件Bean命名
Spring会给每个Bean一个Id,在前面的例子中,尽管没有为SgtPeppers 设置Id,但Spring会根据类名为其制定一个Id,默认是第一个字母变为小写即(sgtPeppers)
如果想为这个bean设置不同的Id,只需将期望的ID作为值传递给@Component,例如
@Component("MySong")
public class SgtPeppers implements CompactDisc {
}
还有另外一种为bean命名方式,这种方式是不使用@Component注解,而是使用Java依赖注入规范中的@Name来设置ID,Spring支持将@Name作为@Component注解的替换方案,但是在Spring中语义不强,不推荐。
设置组件扫描的基础包
@ComponentScan的默认规则是以配置类所在的包作为基础包来扫描组件,但是如果你想扫描多个基础包或扫描不同的包,那该怎么办?
你可以在@ComponentScan的value属性中指明包的名称
@Configuration
@ComponentScan("soundsystem")
public class CDPlayerConfig {
}
如果你想更加清晰地表明你所设置的是基础包,那么可以通过basePackages进行配置
@Configuration
@ComponentScan(basePackages = "soundsystem")
public class CDPlayerConfig {
}
basePackages支持复数的形式,可以设置多个基础包
@Configuration
@ComponentScan(basePackages = {"soundsystem","video"})
public class CDPlayerConfig {
}
设置基础包这种方法是不太安全的,一旦重构代码,那么你所指定的基础包就很有可能出错(因为设置基础包是String类型表示),除了将包设置为简单的String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所包含的类或接口。
@Configuration
@ComponentScan(basePackageClasses = {CDPlayer.class})
public class CDPlayerConfig {
}
basePackages 属性被替换成basePackageClasses ,不再使用String类型的名称来指定包,为basePackageClasses 属性所设置的数组中包含了类,这些类所在的包将会作为组件扫描的基础包
通过为bean添加注解实现自动装配
自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文寻找匹配某个bean需求的其他bean,为了声明要进行自动装配,可以借助@Autowired注解。
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
@Autowired注解不仅能够用在构造器上,还能使用在类的任何方法上。
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
/* @Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}*/
public void play() {
cd.play();
}
@Autowired
public void setCompactDisc(CompactDisc cd) {
this.cd = cd;
}
}