二、Spring4 装配Bean

Spring提供了三种主要的装配机制:

(1)在XML中进行显式配置

(2)在Java中进行显式配置

(3)隐式的bean发现机制和自动装配

一、自动化装配bean:

Spring从两个角度来实现自动化装配:

(1)组件扫描(component-scan):Spring会自动发现应用上下文中所创建的bean

(2)自动装配(autowiring):Spring自动满足bean之间的依赖

POJO:

//CD的一个接口
public interface CompactDisc {
    void play();
}
@Component
public class SgtPeppers implements CompactDisc{

    private String title="Sgt. Pepper's Lonely Hearts Club Band";
    private String artist="The Beatles";

    @Override
    public void play() {
        System.out.println("Playing "+title+" by "+artist);
    }
}
@Configuration
//组件扫描默认是不启用的,所以需要使用该注解开启;
// @ComponentScan默认会扫描与配置类相同的包以及这个包下的所有子包,查找带有@Component注解的类。
@ComponentScan
public class CDPlayerConfig {

}

maven:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.23.RELEASE</version>
        </dependency>

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {

    @Autowired
    private CompactDisc cd;

    @Test
    public void cdShouldNotBeNull(){
        Assert.notNull(cd,"cd Should Not Be Null !!!");
        System.out.println(cd);
    }
}

二、显式装配:

尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化配置是更为推荐的方式,但有时候自动化配置的方案行不通,因此需要明确配置Spring。比如说,你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了。

在这种情况下,你必须要采用显式装配的方式。在进行显式配置的时候,有两种可选方案:Java和XML。在进行显式配置时,JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构友好。

 

(1)Java Config示例

该选择构造器注入还是属性注入呢?作为一个通用的规则,对强依赖使用构造器注入,而对可选性的依赖使用属性注入

@Configuration
public class CDPlayerConfig {

    @Bean
    public Quest quest(){
        SlayDragonQuest slayDragonQuest = new SlayDragonQuest(System.out);
        return slayDragonQuest;
    }
    //直接通过构造器注入
    @Bean
    public Knight knight1(Quest quest){
        BraveKnight braveKnight = new BraveKnight(quest);
        return braveKnight;
    }
    //通过调用方法返回值注入,虽然此处调用了quest()方法,但是由于spring拦截器的作用,实际生成的只有一个Quest的实例(单例)
    @Bean
    public Knight knight2(){
        BraveKnight braveKnight = new BraveKnight(quest());
        return braveKnight;
    }

    //如果有多个构造方法,可以使用set方法或者其他方法注入

}

(2)XML注入示例

public class BlankDisc implements CompactDisc{

    private String title;
    private String artist;
    private List<String> tracks;
    private List<Object> objectList;

    public BlankDisc() {
    }

    public BlankDisc(String title, String artist, List<String> tracks, List<Object> objectList) {
        this.title = title;
        this.artist = artist;
        this.tracks = tracks;
        this.objectList = objectList;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public void play() {
        System.out.println("Playing "+title+" by "+artist);
        for (String track : tracks) {
            System.out.println("-Track: "+track);
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="obj" class="java.lang.Object"></bean>

     <beans>
        <bean id="compactDisc" class="com.chapter2.BlankDisc">
            <!--可以通过artist或者index都行-->
            <constructor-arg index="0" name="title" value="Sgt.Pepper's Lonely Hearts Club Band"/>
            <constructor-arg index="1" name="artist" value="The Beatles"/>
            <constructor-arg index="2" name="tracks">
                <!--注入实际value到list属性-->
                <list>
                    <value>Sgt.Pepper's Lonely Hearts Club Band</value>
                    <value>With a Little Help from My Friends</value>
                    <value>Lucy in the Sky with Diamonds</value>
                    <value>Getting Better</value>
                    <value>Fixing a Hole</value>
                    <!--...-->
                </list>
            </constructor-arg>
            <!--注入引用列表-->
            <constructor-arg name="objectList">
                <list>
                    <ref bean="obj"></ref>
                </list>
            </constructor-arg>
        </bean>
        <bean id="compactDisc2" class="com.chapter2.BlankDisc">
            <property name="title" value=""/>
        </bean>
    </beans>
</beans>

JavaConfig、@ComponentScan、xml等注入方式可以同时结合使用,优先推荐自动扫描和JavaConfig:

@Configuration
public class CDConfig {

    @Bean
    public CompactDisc compactDisc(){
        return new SgtPeppers();
    }
}
@Configuration
public class CDPlayerConfig {

    @Bean
    public CDPlayer cdPlayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }
}
@Configuration
public class QuestConfig {

    @Bean
    public Quest quest(){
        Quest slayDragonQuest = new SlayDragonQuest(System.out);
        return slayDragonQuest;
    }
}

 

@Configuration
@Import({QuestConfig.class})
public class KnightConfig {

    @Bean
    public Knight knight1(Quest quest){
        Knight braveKnight = new BraveKnight(quest);
        return braveKnight;
    }
}

使用@ImportResource标签可以在JavaConfig中引入xml文件 

 

@Configuration
//使用ImportResource标签引入xml配置文件
@ImportResource({"classpath:/META-INF/spring/spring.xml"})
public class XmlConfig {

}

 可以在一个或者多个JavaConfig根据用途或者结构把相关的JavaConfig配置类通过@Import归类到一个配置类中

 

@Configuration
//通过@Import注解将多个配置结合到一起,这些配置就可以互相引用了,也可以在用到其他config的类上单独import
@Import({QuestConfig.class, KnightConfig.class})
public class Chapter1Config {

}

 

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Chapter1Config.class, Chapter2Config.class, XmlConfig.class})
public class CDPlayerTest {

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值