Spring配置的可选方案
- 在XML中进行显式配置
- 在Java中进行显式配置
- 隐式的bean发现机制和自动装配(建议使用自动装配)
自动化装配Bean
组件扫描(component scanning): Spring会自动发现应用上下文中所创建的bean
示例: CD播放
定义CD的概念
public interface CompactDisc { void play(); }
实现某个专辑
@Component public class Numb implements CompactDisc{ private String title = "Numb"; private String artist = "Linkin Park"; @Override public void play() { System.out.println("Play " + title + " by " + artist); } }
@Component
注解表明该类会作为组件类
实现CD播放机配置
@Configuration @ComponentScan public class CDPlayerConfig { }
@ComponentScan
会扫描与配置类相同的包,查找带有@Component
注解的类,并自动为其创建一个bean- 或者使用XML来启动组件扫描(使用时Junit中需要修改注解为
@ContextConfiguration(locations="classpath:beans.xml")
)
<context:component-scan base-package="com.eric.example"/>
测试类
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc cd; @Test public void cdSholudNotBeNull(){ assertNotNull(cd); } }
SpringJUnit4ClassRunner
会自动创建Spring的应用上下文@ContextConfiguration
表明需要加载CDPlayerConfig
中的配置CDPlayerConfig
类中包含了@ComponentScan
,因此应用上下文中会创建对应的CompactDisc
bean
为组件扫描的bean命名
- Spring会根据类名为bean指定一个ID,也就是将类名的第一个字母变为小写
- 可以通过
@Component
来指定ID,@Component("numb")
指定ID为numb
- 通过
@Named
来指定ID,@Named("numb")
指定ID为numb
设置组件扫描的基础包
- 使用
@ComponenetScan(basePackages)
:
@ComponentScan
默认会议配置类所在的包来扫描组件@ComponentScan("com.eric.example")
会扫描com.eric.example
下的组件- 等同于
@ComponentScan(basePackages="com.eric.example")
- 传入
basePackages
参数可以设置多个包,@ComponentScan(basePackages={"com.eric.example", "com.eric.example2"})
- 但是此方法是类型不安全的,重构代码可能会导致基础包错误
- 使用
@ComponenetScan(basePackageClasses)
:
@ComponenetScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
- 这些类所在的包将会作为组件扫描的基础包
- 可以考虑在包中创建空标记接口来避免代码重构导致的问题
- 使用
自动装配(autowiring): Spring**自动满足bean之间的依赖**
示例:
CD播放器
@Component public class CDPlayer { private CompactDisc cd; @Autowired public CDPlayer(CompactDisc cd) { this.cd = cd; } public void play() { cd.play(); } }
@Autowired
可以使用任何将bean作为参数的方法- 如果没有匹配的bean,在应用上下文创建的时候,Spring会抛出异常
测试类
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc cd; @Autowired private CDPlayer cp; @Test public void cdSholudNotBeNull(){ assertNotNull(cd); } @Test public void cpTest() { assertNotNull(cp); cd.play(); } }
其他类与组件扫描中的类一致
通过Java代码装配bean
- 在进行显式配置时,JavaConfig对重构友好
在JavaConfig中声明bean需要编写一个带有
@Bean
的方法通过调用方法引用bean
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Test public void cdSholudNotBeNull(){ assertNotNull(numb()); } @Test public void cpTest() { assertNotNull(cdPlayer()); } }
在配置类中声明bean
@Configuration public class CDPlayerConfig { @Bean public CompactDisc numb() { return new Numb(); } @Bean public CDPlayer cdPlayer(CompactDisc cd) { return new CDPlayer(cd); } }
- 添加了
@Bean
的方法,Spring会拦截所有对它的调用,而为默认都是单例
- 添加了
通过XML配置文件装配bean
声明bean
通过标签
<bean/>
声明<bean name="numb" class="com.eric.example4.Numb"></bean>
构造器注入bean引用
注入对象
<bean name="cp" class="com.eric.example4.CDPlayer"> <constructor-arg ref="numb"></constructor-arg> </bean>
注入值
<bean name="cp" class="com.eric.example4.CDPlayer"> <constructor-arg value="example"></constructor-arg> </bean>
注入集合
<bean name="cp" class="com.eric.example4.CDPlayer"> <constructor-arg> <list> <value>value1</value> <value>value2</value> <value>value3</value> </list> </constructor-arg> </bean>
也可以将
list
中的value
用ref
代替
设置属性
注入对象
<bean name="cp" class="com.eric.example4.CDPlayer"> <property name="compactDisc" ref="numb"/> </bean>
注入值
<bean name="cp" class="com.eric.example4.CDPlayer"> <property name="compactDisc" value="Spring Framework"/> </bean>
小结
自动化装配Bean:
- 需要启动组件扫描: 包含XML配置和Config类配置两种方式,不启动将无法创建bean
- 通过
@Autowired
自动装配
JavaConfig装配Bean:
- 在方法上添加
@Bean
注解,通过调用方法来引用Bean
- 在方法上添加
XML配置文件装配Bean:
- 较为冗杂,一般更倾向于使用自动化装配
关于
@Component
和@Configuration
区别@Component
: 一般结合组件扫描进行使用(自动化装配)@Configuration
: 通常与@Bean
结合使用,作为配置类的注解。其中@Bean
注解的方法,会产生单例的Bean,并且由Spring进行管理
三种装配方式可以结合使用,视具体情况来灵活选择。但尽可能使用自动化装配
- 使用显式装配,尽可能使用基于Java的配置