Spring实战(二)-自动化配置(注解配置)

前言

上一篇我们简单的介绍了DIAOP,并在其中以简单的小例子对其进行讲解,在例子中,我们使用了Spring三种主要装配机制的一种:在XML中进行显示的配置,内容见:Spring实战(一)-DI和AOP入门 而在这里,我们将对Spring的三种装配方式进行详细的介绍

Spring容器负责创建应用程序中的bean并通过DI来协调这些对象的关系,但作为开发人员,我们需要根据自己的需要来告诉Spring要创建哪些bean并选择其装配方式,它提供了以下三种装配方式:

  1. 在XML中进行显示配置
  2. 在Java中进行显示配置
  3. 隐式的bean发现机制和自动装配

以下对自动化配置进行介绍

自动化装配Bean

自动装配能够将显示配置降低到最少,Spring从以下两个角度来实现自动化装配:

  1. 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的Bean
  2. 自动装配(autowiring):Spring自动满足Bean之间的依赖

为了更好的理解组件扫描和自动装配的概念,我们创建几个Bean,它们代表一个印象系统中的组件。类CD为唱片类,Spring会发现它并将其创建为一个bean。类CDPlayer,让Spring发现它,并将CD 这个创建好的bean注入进来。
代码如下:

// 定义CD接口
package music;
public interface CD{
    //唱片具有播放的功能
    void play();
}

// 定义CD接口的实现类
package music;
@Component
public class CnCD implements CD{
    private String title = "中国唱片";

    public void play(){
        System.out.println("Playing " + title);
    }
}

可以看出,我们在CnCD类中添加了@Component注解,这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。
但组件扫描默认是不启用的,还需要显示配置一下Spring,使它去寻找带有@Component注解的类,并为其创建bean,如下代码,在CDPlayer中开启组件扫描:

package music;
import org.springframework.context.annotation.componentScan;
import org.springframework.context.annotation.Con;

@Configuration
@ComponentScan
public class CDPlayer{}

类CDPlayer通过Java代码定义了Spring 的装配规则,在这个类中,并未显示的声明任何bean,只不过它使用了@ComponentScan注解,它能够启用组件扫描。
若你想使用XML来启动组件扫描,那么可以在spring.xml中添加如下代码:

<context:component-scan base-package="music" />

接下来我们做一个简单的JUnit测试,它会创建Spring上下文,并判断CD是不是真的被创建出来了,代码如下:

package music;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayer.class)
public class CDPlayerTest{
    @Autowired
    private CD cd;

    @Test
    public void cdShouldNotBeNull(){
        assertNotNull(cd);
    }
}

其中的@RunWith(SpringJUnit4ClassRunner.class)使其自动创建Spring的应用上下文,注解@ContextConfiguration会告诉它要在CDPlayer中加载配置,而在CDPlayer中包含了@Component,因此最终的应用上下文中应该包含CD这个Bean;

在上一篇文章中,我们获取Spring应用上下文后,会根据spring.xml中配置的beanid来获取对应的bean,但在上述的自动配置中,我们并未配置这个id的值,那么,它又是怎么样给这个bean命名的呢?

  1. 未设置id时,Spring会根据类名给其指定一个id值。具体在这个例子中,id的值为cnCD,将类型的第一个字母变为小写作为bean的id值。
  2. 若想为这个bean设置不同的ID,可在@Component注解中传入期望的id值,如下:
@Component("diffCD")
public class CnCD implements CD{...}

另外,还有一种为bean命名的方式,Spring中支持@Named作为@Component注解的方案,二者有些细微的差别,但在大多数场景下,它们可以相互替换:

package music;
import javax.inject.Named;

@Named("diffCD")
public class CnCD implements CD{...}

到目前为止,在@ComponentScan注解中为设置任何属性,按照默认的规则,它会以配置类所在的包为基础包(base package)来扫描组件。可通过如下几种方式配置:

@Configuration
@Component("music")
public class CDPlayer(){}

--------------------------------------------------

@Configuration
@Component(basePackages="music")
public class CDPlayer(){}

--------------------------------------------------
// 可配置扫描多个包
@Configuration
@ComponentScan(basePackages={"music", "video"})
public class CDPlayer(){}

--------------------------------------------------
// 可配置扫描多个包,参数以String类型是类型不安全(not type-safe)的,因此可以如下配置
@Configuration
@ComponentScan(basePackages={CDPlayer.class, DVDPlayer.class})
public class CDPlayer(){}

通过为bean添加注解(@Autowired)实现自动装配

1.构造器注入

package music;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MediaPlayer{
    private CD cd;

    @Autowired
    public CDPlayer(CD cd){
        this.cd = cd;
    }

    public void play(){
        cd.play();
    }
}

2.setter方法注入

@Autowired
public void setCD(CD cd){
    this.cd = cd;
}

实际上,@Autowired注解可以作用在类的任何方法上,只要添加了该注解,Spring都会尝试满足方法参数上所声明的依赖。如果有且只有一个bean匹配依赖,那么这个bean就会被装配进来。如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常,为了避免这个异常出现,可将@Autowiredrequired属性设置为false

@Autowired(required=false)
public CDPlayer(CD cd){
    this.cd = cd;
}

注:此设置需谨慎,required属性设置为false时,Spring尝试自动装配若没有匹配的bean,则会让这个bean处于未装配的状态。但若你在代码中没有进行null检查的话,这个处于未装配状态的属性就有可能会出现NullPointerException

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值