一、装配Bean
1.1 Spring配置的可选方案
Spring主要提供三种主要的装配机制:
- 在XML中进行显式配置
- 在java中进行显式配置
- 隐式的bean发现机制和自动装配
1.2 自动化装配Bean
Spring从两个角度来实现自动化装配:
- 组件扫描:Spring会自动发现应用上下文中所创建的bean
- 自动装配:Spring会自动满足bean之间的依赖
这两种方法组合在一起就能发挥出强大的威力,他们可以将显示配置降低到最少
1.2.1 创建可被发现的bean
如下实例:
CompactDisc接口
package com.cf.springinaction;
public interface CompactDisc {
void play();
}
SgtPeppers实现类
package com.cf.springinaction;
import org.springframework.stereotype.Component;
/**
* component注解表明这个类会作为组件类,并告知Spring要为这个类创建bean
* 使用此注解可以不用显式配置SgtPeppersBean
*/
@Component
public class SgtPeppers implements CompactDisc {
private String title = "Sgt, Pepper's Lonely Hearts Club Sand";
private String artist = "The Beatles";
public void play() {
System.out.println("Playing " + title + " by" + artist);
}
}
配置类
package com.cf.springinaction;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* ComponentScan注解启动组件扫描,扫描与配置类相同的包以及下层的子包
*
* 如果使用xml来其中组件扫描则为
* <context:component-scan base-package="....></context:component-scan>
*/
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
测试类(测试通过)
1.2.2 为组件扫描的bean命名
Spring应用上下文中所有的bean都会给定一个ID。上例,尽管没有明确地为SgtPeppers Bean设置ID,但Spring会根据类名为其指定一个ID。ID名为sgtPeppers,将类名的第一个字母变为小写
如果想为这个bean设置为不同的ID,就要将期望的ID作为值传递给@Component注解。
@Component("lonelyHeartsClub")
1.2.3 设置组件扫描的基础包
@ComponentScan无任何属性设置,则按默认规格,他会以配置类所在的包作为基础包(base package)来扫描组件。
当把配置类放在单独的包中,使其与其他的应用代码区分开来。那默认的基础包就不能满足要求了。需要在@ComponentScan的value属性中指明包的名称
@ComponentScan("包名")
或清晰的使用basePackages属性设置
@ComponentScan(basePackages="包名")
也可以设置多个包,将basePackages属性设置为要扫描包的一个数组即可:
@ComponentScan(basePackages={"包名1","包名1"})
还可以将其指定为包中所含的类或接口,这些类所在的包将会作为组件扫描的基础包
@ComponentScan(basePackageClasses = {CompactDisc.class,SgtPeppers.class})
可以考虑在包中创建一个用来进行扫描的空标记接口(marker interface)。这样,依然能够保持对重构友好的接口引用,但是可以避免引用任何实际的应用程序代码
1.2.4 注解实现自动装配
自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。
package com.cf.springinaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
//在构造器上添加Autowired注解
//表明Spring创建CDPlayer Bean时,会通过这个构造器来进行实例化并且会传入一个可设置CompactDisc类型的bean
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
@Autowired注解可以用在类的任何方法上,Spring都会尝试满足方法参数上所声明的依赖。假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。
如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。
如果有多个bean都满足的化,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行装配
1.3 通过Java代码装配bean
通过组件扫描和自动装配实现Spring的自动化配置是更为推荐的方式,但有时候自动化配置的方案行不通,因此需要明确配置Spring。
比如,将第三方库中的组件装配到应用中,这种情况下是没有办法在它的类上添加@Component和@Autowired注解的,因此不能使用自动化装配的方案。
在这种情况下,必须采用显示装配。有两种方案:Java和XML
1.3.1 创建配置类
通过JavaConfig显示装配Spring,其关键在于@Configuration注解,@Configuration表明这个类是一个配置类
在此移除CDPlayerConfig的@ComponentScan注解,这是bean就不会自动