《Spring实战》-第二章:Bean的装配(2)-JavaConfig显式装配

慢慢来比较快,虚心学技术

前言:创建应用对象之间协作关系的行为通常称为装配( wiring ),这也是依赖注入( DI )的本质

Spring提供三种Bean装配机制:

  1. 在 XML 中进行显式配置。
  2. 在 Java 中进行显式配置
  3. 隐式的 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}.
    * <p>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.
    * <p>If left unspecified, the name of the bean is the name of the annotated method.
    * If specified, the method name is ignored.
    * <p>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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章