spring--装配bean

    众所周知,spring最基本的功能就是用来管理bean,spring为我们提供了三种装配bean的方式:
     1. XML显式配置
     2. Java显式配置
     3. 组件扫描和自动装配

    一般来说,我们肯定是希望让我们显式配置的越少越好,所以,我们一般都会以组件扫描和自动装配为主,Java显式配置和XML显式配置为辅,至于到底使用哪一种,还是看项目的需要和你个人的喜好.

1. 组件扫描

1.1 例子

    spring通过组件扫描和自动装配来帮助我们完成一些复杂的依赖关系,下面我们用一个CD播放器的例子来说明spring的组件扫描.
    首先,我们定义个CD播放机的接口:
public interface CompactDisc {
    void play();
}
    然后,定义一个类去实现这个接口,这里也没有什么特别的地方,主要就是我们通过@Component去修饰了该类,这个注解的作用就是告知spring,我们要将这个类作为一个bean,需要spring在容器中创建这个bean:
@Component
public class CompactDiscImpl implements CompactDisc {
    public void play() {
        System.out.println("play");
    }
}
    不过,到目前为止,我们还没有开启spring的组件扫描功能,所以我们要启用spring的组件扫描功能,有两种方式可以开启,一种是通过Java配置,一种是通过XML配置:
    Java配置,可以看出来@ComponentScan就是配置自动扫描的注解,该注解会默认扫描该配置类包和子包下的所有类,如果需要指定包去扫描,需配置:
@Configuration
@ComponentScan
public class SpringConfig {
}
    XML配置中,只需要加一句话即可,<context:component-scan base-package="指定包">.

    之后,我们就可以测试该例子,创建一个JUnit单元测试,@RunWith(SpringJUnit4ClassRunner.class)的作用就是测试开始时自动创建Spring上下文,@ContextConfiguration(classes = SpringConfig.class)的作用就是告诉Spring从SpringConfig类中加载配置信息:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class Test {

    @Autowired
    private CompactDisc cd;

    @org.junit.Test
    public void test() {
        Assert.assertNotNull(cd);
    }
}
    运行一下,应该会发现测试通过,因为cd通过Spring的@Autowired自动注入进去了,所以不为null.

1.2 细节配置

    Spring应用上下文为每一个bean都会有一个给定的id,在上面的例子中,虽然我们没有明确的给CompactDiscImpl设置id,但是Spring会默认给其设置一个id,就是compactDiscImpl,就是将首字母小写.
    如果你想为这个bean设置不同的id,可以这样做:@Component("myId"),也就是利用@Component注解来为bean自定义id.

    上例中,还有一个注解@ComponentScan,该注解是开启自动扫描注解,会默认扫描所修饰类所在包和其子包,当然,我们也可以指定具体的包进行扫描,可以这样制定:@ComponentScan("myPackage").
    当然,我们可以更为清晰的指定@ComponentScan(basePackageClasses = "myPackage"),如果你想指定多个包呢,那也是可以的,如@ComponentScan(basePackageClasses = {"myPackage1","myPackage2"}).
    有些时候,利用字符串指定所要扫描的包是不安全的,比如你重构项目时,包可能会发生改变,所以我们也可以通过指定类或接口去扫描该类或接口所在的包,例如:@ComponentScan(basePackageClasses = {"MyClass1.class","MyClass2.class"}),通常我们会创建一个空接口放在该包下,然后去用这种注解方式去引用,防止在重构过程中,删除了使用的业务相关类.

2. 自动装配

    简单的说,自动装配就是Spring将类的依赖关系自动组合在一起,比如A类依赖B类,如果使用自动装配,Spring就会将B自动注入到A中,而不用我们在A类中实例化B类.

    Spring中一般是使用@Autowired注解来实现自动装配,@Autowired注解可以用在类的任何方法上,不管是构造器,还是set方法,还是其他方法,Spring都会去满足方法参数上所申明的依赖.
    假如有且只有一个bean匹配依赖的需求的话,那么这个bean将会被装配进来.
    如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常,为了避免异常的出现,你可以将@Autowired的required属性设置为false:@Autowired(required=false),但是这意味着如果没有匹配到合适的bean,该bean将会为null,调用时应该加以判断,否则会出现空指针异常.
    如果匹配到多个合适的bean的话,Spring也会抛出异常,表明没有明确指定选择哪个bean进行装配.

3. 通过Java代码装配bean

    从理论上来说,我们应该都采用组件扫描和自动装配的方式来进行自动化配置,但难免有一些特殊情况,比如我们要使用第三方包的组件装配到我们的应用中,但这种情况下,我们无法再它的类上添加@Component或者是@Autowired,因此就不能使用自动装配,而要采用显式的配置.显式配置有两种方式,一种是通过Java代码,一种是通过XML配置文件,这里我们首先介绍使用Java代码来装配bean.

    也许你还记得,在前面的例子中,有一个SpringConfig,这个类使用了@Configuration注解,这个注解就是申明该类是一个配置类,该类包含了Spring应用上下文如何创建bean.
    例如,我们这里有A类和B类,A类依赖于B类,我们在配置类中就可以这样写:

    @Bean注解会告诉Spring,这个方法将会返回一个对象,这个对象要注册成为Spring应用上下文中的bean.
    当然,前面我们也提到过,每个bean都是有一个id的,下面这个例子中,B的bean的id就是getB,也就是方法名,如果你要自己自定义的话,可以使用@Bean(name = "myName"),并且因为是使用Java代码来进行配置,我们可以在return new B();之前做非常多的事情,比如B有很有子类,我们可以随机构造一个B的子类实例返回.
    因为A依赖于B,所以我们希望将B注入到A中,我们可以使用return new A(getB()),这样使用时,其实Spring并不会去调用getB()方法,因为被@Bean修饰的方法的调用都会被阻断,当我们使用getB()方法时,其实是Spring阻断了该方法的调用,并且返回了Spring所创建的bean.  
    当然,注入方法一的使用十分局限,比如我两个Bean并没有写在一个配置类中,或者B是自动扫面的,或者B是XML所配置的,所以,我们还是应该使用注入方法二,这意味着只要B这个bean存在于Spring应用上下文中,不管是怎么创建出来的,我都可以将其注入到A中.
@Configuration
public class JavaConfig{
    @Bean
    public B getB(){
        return new B();

    // 注入方法一
    @Bean
    public A getA(){
        return new A(getB());
    }

    //注入方法二
    @Bean
    public A getA(B b){
        return new A(b);
    }
}

4. 通过XML装配bean

    XML配置在三种配置上来说,是属于比较繁琐的,而且基本上XML配置能实现的,Java配置都可以实现,Java配置可以实现的,XML缺实现不了(就比如说之前例子中,可以随机装配B类子类的bean).
    但是由于目前,还是有非常多的项目是使用XML配置来装配bean的,所以此处也会介绍一些XML配置的基本用法.


    要在XML配置文件中申明一个bean,我们可以使用<bean>,并使用class标识类的位置,使用id来申明该bean的id,Spring默认会调用该类的默认构造器来创建该bean:
<bean class="class position" id="myName" />
    当我们要使用XML进行bean注入时,可以这样做,我们依然使用A类依赖于B类的例子:
    <constructor-arg>是使用构造器注入,当Spring实例化A类时,<constructor-arg>会告知Spring,A类需要一个id为b的bean传入到其构造器中.(如果构造器需要多个参数,就写多个<constructor-arg ref="xxx"/>即可)
    有时候我们可能需要传入一些字面量注入到类中,比如字符串,这时我们可以使用<constructor-arg value="string"/>,ref换成了value.
<bean id="b" class="b class position"/>

<bean id="a" class="a class position">
    <constructor-arg ref="b"/>
</bean>
    除了使用构造器来注入bean,我们也可以使用set方法来注入bean,property中的name就是属性的名称,ref就是该属性引用的bean的id:
<bean id="b" class="b class position"/>

<bean id="a" class="a class position">
    <property name="b" ref="b" />
</bean>

5. 导入和混合配置

    在实际的开发中,我们可能会遇到一些特殊的情况:

    1.我们使用Java配置的时候,如果配置信息过多,我们要分到好几个配置类中进行配置,我们可以使用@Import(xxx.class)将配置类导入到其他配置类中.这里假设我们有A和B两个配置类.
@Configuration
public class A{
}
@Configuration
@Import(A.class)
public class B{
}
    或者我们使用第三个空的配置类C来导入A和B两个类.

    2.我们要在Java配置中引用XML配置,我们可以使用注解@ImportResource:
@Configuration
@Import(A.class)
@ImportResource("classpath:spring.xml")
public class B{
}
    3.在XML配置中引用XML配置:
<import resource="xxx.xml">
    4.在XML配置中引用Java配置,可以直接将Java配置类定义为一个<bean>


    到这,spring的装配bean就介绍完了.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值