慢慢来比较快,虚心学技术
前言:创建应用对象之间协作关系的行为通常称为装配( wiring ),这也是依赖注入( DI )的本质
Spring提供三种Bean装配机制:
- 在 XML 中进行显式配置。
- 在 Java 中进行显式配置
- 隐式的 bean 发现机制和自动装配
一、为什么使用JavaConfig显式配置?
相比于XML显式配置,javaConfig显然是更好的方案
- Ⅰ.本就是java代码,便于重构管理
- Ⅱ.类型安全,更为强大
- Ⅲ.配置方便,简洁
二、怎么配置?
java显式配置:类似于XML配置模式,显式配置每个Bean的名称
在实现之前我们需要了解一下几个基本注解:
@Autowired :标记于属性,方法等,自动装配的关键注解,依赖注入的表现,该注解可以自动寻找并从Spring容器中提取使用该注解的bean并注入到对应的属性中去
@Bean:该注解用于配置类中,注明某方法是装配方法,方法名就是装配的Bean名称(javaConfig显式配置的核心注解)
@Configuration :标记于配置类,标明当前类是一个配置类
① 与上一篇文章一样,基础类代码不变。
public class CDBean {
/**
* 定义CD名
*/
private String title="The World!";
/**
* 定义CD作者
*/
private String author="Mr.D";
}
② CDPlayerImp类增加CDPlayerImpl(CDBean cdBean)构造方法,方便后续注入
public class CDPlayerImpl implements CDPlayer {
private CDBean cdBean;
public CDPlayerImpl() {
super();
}
public CDPlayerImpl(CDBean cdBean) {
super();
this.cdBean = cdBean;
}
@Override
public void playCD() {
System.out.println("正在播放:"+cdBean.getTitle()+" by "+cdBean.getAuthor());
}
}
③ CDConfig类更改配置方式,显式配置每一个类
@Configuration//标明配置
public class CDConfig {
@Bean
public CDBean cdBean(){
return new CDBean();
}
@Bean
public CDPlayer cdPlayer(){
return new CDPlayerImpl(cdBean());
}
}
④注解测试,将配置类指向CDConfig2
此处使用Spring提供的测试类SpringJUnit4ClassRunner帮助测试,以便在测试开始的时候自动创建 Spring 的应用上下文,而@ContextConfiguration可以指定创建上下文的加载方式以及配置的位置等
@RunWith(SpringJUnit4ClassRunner.class)//使用Spring提供的测试包进行测试,主要帮助实现bean的装载环境
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {CDConfig2.class})//配置类指向CDConfig2
public class AppTest
{
//使用注解自动注入
@Autowired
private CDPlayer cdPlayer;
/**
* Rigorous Test :-)
*/
@Test
public void play()
{
this.cdPlayer.playCD();
}
}
⑤测试结果:
正在播放:The World! by Mr.D
⑥Spring提供另一种测试方式,通过Spring应用上下文AnnotationConfigApplicationContext上下文实现进行测试
public class App
{
public static void main(String[] args) {
/**
* 之所以要指定配置类,相当于,写了xml文件也一样需要指定xml文件位置一样,spring并不能自动开启注解并读取配置
*/
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(CDConfig2.class);
//获取应用上下文中的所有Bean名称
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String className : beanDefinitionNames){
System.out.println(className);
}
CDPlayer cdPlayer = applicationContext.getBean(CDPlayer.class);
cdPlayer.playCD();
}
}
⑦ 测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
CDConfig2
cdBean
cdPlayer
正在播放:The World! by Mr.D
注:
Ⅰ、@Bean注解可以为Bean另起ID,源码中有属性如下,name属性是一个用{}包围起来字符串数组,表明可以定义多个id:
public @interface Bean {
/**
* Alias for {@link #name}.
* Intended to be used when no other attributes are needed, for example:
* {@code @Bean("customBeanName")}.
* @since 4.3.3
* @see #name
*/
@AliasFor("name")
String[] value() default {};
/**
* The name of this bean, or if several names, a primary bean name plus aliases.
*
If left unspecified, the name of the bean is the name of the annotated method.
* If specified, the method name is ignored.
*
The bean name and aliases may also be configured via the {@link #value}
* attribute if no other attributes are declared.
* @see #value
*/
@AliasFor("value")
String[] name() default {};
}
由上述源码可做如下更改:
@Configuration
public class CDConfig2 {
@Bean(name = {"CDBEAN"})
public CDBean cdBean(){
return new CDBean();
}
@Bean
public CDPlayer cdPlayer(){
return new CDPlayerImpl(cdBean());
}
}
执行⑥测试结果如下:CDBean的装配ID已成功更改
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
CDConfig2
CDBEAN
cdPlayer
正在播放:The World! by Mr.D
Ⅱ、@Bean注解的使用,内部注入不只是能在构造方法内,还可以在setter和普通方法等注入
@Configuration
public class CDConfig2 {
@Bean(name = {"CDBEAN"})
public CDBean cdBean(){
return new CDBean();
}
@Bean
public CDPlayer cdPlayer(){
CDPlayer cdPlayer = new CDPlayerImpl();
cdPlayer.setCDBean(cdBean());//在setter方法中注入
}
}
总结
1、JavaConfig显式配置相对于XML显式配置来说,具有配置简单,维护方便的优点
2、JavaConfig显式配置主要依赖于@Bean注解和@Configuration两个注解实现,其中@Configuration注解标明当前类为配置类,而@Bean使用在配置类中的方法内,定义一个装配类名为方法名的Bean
3、Spring使用@Autowired进行依赖注入
4、Spring中我们可以通过两种方式方便的对javaConfig显式配置进行测试,一种是结合SpringJUnit4ClassRunner模拟装配环境进行测试,一种是使用应用上下文AnnotationConfigApplicationContext进行测试
参考文档
【1】《Spring 实战(第 4 版)》·Craig Walls