01.装配Bean
使用隐式装配
编写组件
使用隐式装配的流程
- 编写组件
为需要被管理的类加上 @Component, 可以设置参数 value 作为 组件的 id. 这个值默认为首字母小写的类名.
@Component(value="player")
public class CDPlayer{
System.out.println("这是一个组件")
}
- 编写配置文件,
配置文件需要两个标签, 一个是 @Configuration, 表示这个类是一个配置类. 一个是 @ComponentScan, 可以设置参数来扫描参数代表的包中的组件(默认为这个配置文件所在的包). 被扫描的组件会被 Spring 管理
其中设置的参数, 有两种写法
-
basePackages: 可以是一个 String, 或者是一个 String 的 数组, 同名的包会被扫描. 顺便说一下, 直接写@ComponentScan("package1"), 用的就是这种方法 -
basePackageClasses: 可以是一个 Class 对象, 或者是一个 Class 的数组, 所指的类所在的包会被扫描
还是比较推荐第二种方法, 因为, 在实际开发过程中是不推荐把某个要实际应用的代码放到这里配置文件, 所以书里有个方法是在组件的包中放一个空的接口, (标记接口 maker interface), 作为配置文件引用的类.
@Configurations
@ComponentScan(basePackageClasses = {Component1.class, Component2.class})
public class ComponentScanner{\\这里啥都不用写}
- 测试
普通的非组件的类要调用组件, 首先要获得一个上下文, 然后从上下文中取用组件. 这里我们用基于 Java 的配置类中加载的上下文, 所以用的是 AnnotationConfigApplicationContext, 使用 getBean 获得组件
public class ComponentTest{
public static void main(String[] args){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CDPlayerConfig.class);
CDPlayer cdplayer = context.getBean("player", CDPlayer.class);
cdplayer.play();
context.close();
}
}
getBean 接受的参数有一个组件名(也就是在 @Component 接受的 value), 和一个 Class 对象. 这两个参数只要有一个就可以用. Spring 会尽可能满足需求. 但是如果没有或者有多个符合条件的组件, 那么就会报错. 要注意的是, 如果不加 Class 对象作为参数, 那么返回的是一个 Objcet 对象, 需要强制类型转换一下.
自动装配
Spring 的特点和优点就在于, 组件和组件之间尽量没有关系, 所有的组装都由 Spring 完成. 组件和组件是必然要有耦合的, 但是, 组件之间的聚合关系, 不需要显式地声明一个对象作为参数参数传给一个对象成为它地属性. 这件事 Spring 会自动完成, 这个过程就是自动装配.
自动装配可以通过注解或者 XML 实现, 这里只讲基于注解的自动装配. @Autowired注解
- @Autowired, 可以用于方法
@Autowired
public void setCD(CompactDisc cd){
this.cd = cd;
}
- 或者属性
@Autowired
private CompactDisc cd;
Spring 会尽量满足需求. 如果有多个 CompactDisc 组件, 那么会尝试匹配组件名与参数名一致的组件. 否则会报错.
如果没有匹配的组件, 那么也会报错, 可以设置 required = false, 忽略这个错误
@AutoWired(required=false)
private CompactDisc cd;
使用JAVA显式装配
在有些时候, 自动装配是无法使用的. 比如要那一个第三方的库作为组件, 跑去在源码里添加 @Component 是不现实的. 这时候就需要显式装配.
打开 Config 文件, 之前使用自动装配的配置是这样的
@Configuration
@ComponentScan(basePackageClasses = {CDplayer.class, ComponentDisc.class})
public class CDPlayerConfig{
}
在显式装配的配置文件中不需要 @ComponentScan 这个组件是用来自动扫描的.
声明简单的bean
声明简单的 bean 很简单, 只需要写一个用 @Bean 修饰的方法, 这个方法返回要管理的组件就可以了
@Bean(name="segPepper")
public ComponentDisc segPepper(){
return new SegPepper();
}
可以不设置 @Bean 的 name 属性, 如果不设置, bean 的 id 默认是这个方法的名称 ---- "player"
需要组装的bean
对于有聚合关系, 引用了另一个组件的组件, 我们也希望在配置文件中完成组件的装配. 有两种方法做这件事
- 调用配置组件的方法: 方法内调用另一个配置的方法, 将获得的组件对象装配.
@Bean
public CDPlayer segPepper(){
return new CDPlayer(segPepper());
}
- 参数传递的方法: 把组件作为参数传给配置方法
@Bean
public CDPlayer player(ComponentDisc cd){
CDPlayer player = new CDPlayer(cd);
return player;
}
需要注意的是, 系统只会加载组件一次, 在第一次调用 segPepper, 返回的组件会被系统管理, 以后在调用这个方法, 系统会拦截这个方法的运行, 并不容器管理的组件返回给调用的一方