创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(Dependence Injection)的本质,在开发基于Spring的应用时,你随时都在使用这些技术,所以弄懂这些,尤其重要。在Spring中装配bean的方式有很多,下面介绍常用的三种装配方式。
自动化装配beanSpring从两个角度来实现自动化装配:
- 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean
-
自动装配(autowiring):Spring自动满足bean之间的依赖
1.创建可被发现的bean,并启用组件扫描。
以CD播放器为例,定义一个CompactDisc的接口和一个MediaPlayer的接口,接口的具体内容并不重要,重要的是你将其定义为一个接口。作为接口,它定义了CD播放器对一盘CD所能进行的操作。
package soundsystem
public interface CompactDisc{
viod play();
}
package soundsystem;
public interface MediaPlayer {
void play();
}
下面是CompactDisc的一个实现类,@Component注解表明该类会作为组件类,并告知Spring要为这个类创建bean。
package soundsystem;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc {
private String title = "Sgt.Pepper Lonely Hearts Club Band";
private String artist = "The beatles";
public void play() {
System.out.println("Playing "+ title + " by " + artist);
}
}
可被发现的bean已创建好,但这个bean只是可被发现,要想真正地被发现还需还需启用组件扫描(组件扫描默认是不开启的)。方法有二:
方法一:创建配置类,通过@ComponentScan启用组件扫描。
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages="soundsystem")
public class CDPlayerConfig {
}
方法二:通过XML文件的配置启用组件扫描。
<context:component-scan base-package="soundsystem"></context:component-scan>
2.通过为bean添加注解实现自动装配
在上面的工作中我们已经能够将bean自动添加到Spring容器中,接下来需实现自动装配来满足bean之间的依赖。
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();
}
}
通过Java代码装配bean
创建配置类,@Configuration注解表明这个类是一个注解类,该类包含了在Spring应用上下文中如何创建bean的细节。与上面不同的是,这里我们移除了@ComponentScan注解,不在用组件扫描的方式加载bean,在这里我们更加关注显示配置
package soundsystem;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig2 {
}
声明bean
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
借助JavaConfig实现注入(可以有多种方法,在这里只提供其中一种)
@Bean
public CDPlayer cdPlayer(CompactDisc cd) {
return new CDPlayer(cd);
}
通过XML装配bean
声明bean
在基于XML的Spring配置中声明一个bean,我们要使用spring-beans模式中的一个元素:<bean>。我们可按照如下方式声明CompactDisc bean:
<bean id="sgtPepper" class="soundsystem.SgtPepper" />
注入bean(方法有二)
其一:构造注入
我们已经声明了SgtPepper bean,并且SgtPepper类实现了CompactDiSC接口,现在我们要做的就是在XML中声明CDPlayer并通过ID引用SgtPepper:
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="sgtPepper" />
</bean>
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("mediaPlayer")
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
其二:设值注入
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<property name="compactDisc" ref="sgtPepper"></property>
</bean>
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public void setCd(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
这些配置方案不是互斥的,你也可以混合配置,建议尽可能使用自动化配置,以避免显示配置所带来的维护成本。