Spring使用篇(四)—— Spring中Bean的高级装配方式

1、装配的混合使用

  在上一篇系列博客《Spring使用篇(三)—— Spring中Bean的基本装配方式》中已经详细介绍了Spring中Bean的基本装配方法,在现实中,使用XML或者注解各有道理,建议在自己的工程中所开发的类尽量使用注解的方式,因为使用它并不困难,甚至可以说更为简单,而对于引入第三方包或者服务的类,尽量使用XML方式,这样的好处是可以尽量对三方包或者服务的细节减少理解,也更加清晰和明朗。

  Spring同时支持这两种形式的装配,所以可以自由地选择XML或者注解的配置方法,无论采用何种方法都是将Bean装配到Spring IoC容器中,这样就可以通过Spring IoC容器去管理各类资源了。

  在在上一篇系列博客《Spring使用篇(三)—— Spring中Bean的基本装配方式》中曾使用CD播放器和CD光盘的例子来讲解通过JavaConfig的显示装配方式去装配Bean,其原始配置代码如下所示:

package com.ccff.spring.assembling.config;

import com.ccff.spring.assembling.pojo.CDPlayer;
import com.ccff.spring.assembling.service.CompactDisc;
import com.ccff.spring.assembling.service.CompactDiscImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CDPlayerConfig {
   

    @Bean
    public CompactDisc compactDiscImpl(){
   
        return new CompactDiscImpl();
    }

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

}

1.1 使用多个JavaConfig配置类

  假设该JavaConfig配置类目前已经变得很笨重,即里面配置了很多Bean。此时需要将其进行拆分,因此准备将CD光盘类从该配置类中拆分出来形成新的配置类进行单独管理。在com.ccff.spring.assembling.config包下创建名为“CDConfig”的CD光盘配置类,具体代码如下所示:

package com.ccff.spring.assembling.config;

import com.ccff.spring.assembling.service.CompactDisc;
import com.ccff.spring.assembling.service.CompactDiscImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CDConfig {
   
    @Bean
    public CompactDisc compactDiscImpl(){
   
        return new CompactDiscImpl();
    }
}

  将CD光盘类拆分出来后,会发现此时的CDPlayerConfig出现了错误,如下图所示,原因和简单,因为CDPlayer和CompactDisc之间具有依赖关系,而此时的CDPlayerConfig中并没有CompactDisc。
在这里插入图片描述
  想要解决这个错误,这就需要将这两个类组合在一起,第一种解决方法就是在CDPlayerConfig中使用注解@Import将CDConfig配置类导入到CDPlayerConfig中,具体代码如下所示:

package com.ccff.spring.assembling.config;

import com.ccff.spring.assembling.pojo.CDPlayer;
import com.ccff.spring.assembling.service.CompactDisc;
import com.ccff.spring.assembling.service.CompactDiscImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(CDConfig.class)
public class CDPlayerConfig {
   
    /*@Bean
    public CompactDisc compactDiscImpl(){
        return new CompactDiscImpl();
    }*/

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

  在com.ccff.spring.assembling.test包下创建名为“TestCD”的测试类,具体代码如下:

package com.ccff.spring.assembling.test;

import com.ccff.spring.assembling.config.CDPlayerConfig;
import com.ccff.spring.assembling.pojo.CDPlayer;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestCD {
   
    private ApplicationContext context;

    @Before
    public void getContext(){
   
        context = new AnnotationConfigApplicationContext(CDPlayerConfig.class);
    }

    @Test
    public void TestBean(){
   
        CDPlayer cdPlayer = (CDPlayer) context.getBean("cdPlayer");
        cdPlayer.playMusic();
    }
}

  运行上面的测试方法TestBean,查看输出到控制台上的日志信息,发现通过注解@Import的方式可以成功将其他JavaConfig配置类引入,具体结果如下所示:
在这里插入图片描述
  或者采用第二种更好的办法,也就是不在CDPlayerConfig中使用注解@Import,而是在com.ccff.spring.assembling.config包下创建一个更高级别的名为“SoundSystemConfig”配置类,在这个配置类使用注解@Import将两个配置类组合在一起,具体代码如下所示:

package com.ccff.spring.assembling.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({
   CDPlayerConfig.class,CDConfig.class})
public class SoundSystemConfig {
   
}

  修改测试类TestCD中的getContext方法,在此引入SoundSystemConfig配置类,具体代码如下所示:

package com.ccff.spring.assembling.test;

import com.ccff.spring.assembling.config.CDPlayerConfig;
import com.ccff.spring.assembling.config.SoundSystemConfig;
import com.ccff.spring.assembling.pojo.CDPlayer;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestCD {
   
    private ApplicationContext context;

    @Before
    public void getContext(){
   
        context = new AnnotationConfigApplicationContext(SoundSystemConfig.class);
    }

    @Test
    public void TestBean(){
   
        CDPlayer cdPlayer = (CDPlayer) context.getBean("cdPlayer");
        cdPlayer.playMusic();
    }
}

  运行上面的测试方法TestBean,查看输出到控制台上的日志信息,发现通过SoundSystemConfig的方式可以成功将其他JavaConfig配置类引入,具体结果如下所示:
在这里插入图片描述

1.2 在JavaConfig配置类中引入XML

  这里需要注意,不管采用哪种方式,都将CDConfig的配置和CDPlayerConfig的配置分开了,只不过此时还是均采用的是JavaConfig的显示装配方式,若此时需要将CD光盘Bean通过XML的方式进行装配,则需要对CompactDisc接口的实现类CompactDiscImpl中的成员属性添加get和set方法,具体代码如下:

package com.ccff.spring.assembling.service;

public class CompactDiscImpl implements CompactDisc {
   
    private String title = "依然范特西";
    private String artist = "周杰伦";

    public String getTitle() {
   
        return title;
    }

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

    public String getArtist() {
   
        return artist;
    }

    public void setArtist(String artist) {
   
        this.artist = artist;
    }

    @Override
    public void play() {
   
        System.out.println("当前正在播放"+artist+"的专辑《"+title+"》");
    }
}

  则在spring-config中添加如下的具体配置:

<!--装配CompactDiscImpl,实现XML与注解的混合使用-->
<bean id="compactDiscImpl" class="com.ccff.spring.assembling.service.CompactDiscImpl">
    <property name="title" value="叶惠美" />
    <property name="artist" value="周杰伦" />
</bean>

  此时我们已经将光盘通过XML的方式进行了配置,但是CD播放器还是通过JavaConfig的方式进行了配置,因此如何让Spring同时加载这两种配置方式呢?

  答案是在Java Config配置类上使用注解@ImportResource,通过该注解将配置在XML中的Bean引入。在本案例中,在CDPlayerConfig配置类中首先注释掉注解@Import,然后使用注解@ImportResource将配置的XML引入,具体代码如下:

package com.ccff.spring.assembling.config;

import com.ccff.spring.assembling.pojo.CDPlayer;
import com.ccff.spring.assembling.service.CompactDisc;
import com.ccff.spring.assembling.service.CompactDiscImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

@Configuration
//@Import(CDConfig.class)
@ImportResource("classpath:spring-config.xml")
public class CDPlayerConfig {
   
    /*@Bean
    public CompactDisc compactDiscImpl(){
        return new CompactDiscImpl();
    }*/

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

  修改测试类TestCD中的getContext方法,让其重新加载CDPlayerConfig配置类,具体代码如下所示:

package com.ccff.spring.assembling.test;

import com.ccff.spring.assembling.config.CDPlayerConfig;
import com.ccff.spring.assembling.pojo.CDPlayer;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestCD {
   
    private ApplicationContext context;

    @Before
    public void getContext(){
   
        context = new AnnotationConfigApplicationContext(CDPlayerConfig.class);
    }

    @Test
    public void TestBean(){
   
        CDPlayer cdPlayer = (CDPlayer) context.getBean("cdPlayer");
        cdPlayer.playMusic();
    }
}

  运行上面的测试方法TestBean,查看输出到控制台上的日志信息,发现通过注解@ImportResource的方式可以成功将其他XML配置引入,具体结果如下所示:
在这里插入图片描述

1.3 在XML中引入JavaConfig配置类

  这里为了演示方便,将之前的项目中涉及到的两个Bean(CD唱片CompactDiscImpl和CD播放器CDPlayer)的配置全部修改为通过XML的方式进行配置。

  首先在为这两个Bean类添加无参构造方法和get、set方法,在此基础上配置spring-config配置文件如下,在XML中实现对Bean的装配,具体配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd">
    <!--Spring Bean配置代码-->
    <!--通过XML配置装配Bean:装配简易值-->
    <bean id="school" class="com.ccff.spring.assembling.pojo.School">
        <property name="school_name" value="中国科学院大学" />
        <property name="school_no" value="Sch001" />
        <property name="school_location" value="北京市怀柔区怀北镇怀北庄中国科学院大学雁西湖校区" />
    </bean>
    <bean id="student" class="com.ccff.spring.assembling.pojo.Student">
        <property name="name" value="学生一" />
        <property name="studentNo" value="S001" />
        <property name="age" value="24" />
        <property name="sex" value="" />
        <property name="school" ref="school" />
    </bean>

    <!--通过XML配置装配Bean:装配字符串集合-->
    <bean id="complexAssembly" class="com.ccff.spring.assembling.pojo.ComplexAssembly">
        <property name="id" value="1" />
        <property name="list">
            <list>
                <value>value-list-1</value>
                <value>value-list-2</value>
                <value>value-list-3</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="key1" value="value-map-1" />
                <entry key="key2" value="value-map-2" />
                <entry key="key3" value="value-map-3" />
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="prop1">value-prop-1</prop>
                <prop key="prop2">value-prop-2</prop>
                <prop key="prop3">value-prop-3</prop>
            </props>
        </property>
        <property name="set">
            <set>
                <value>value-set-1</value>
                <value>value-set-2</value>
                <value>value-set-3</value>
            </set>
        </property>
        <property name="array">
            <array>
                <value>value-array-1</value>
                <value>value-array-2</value>
                <value>value-array-3</value>
            </array>
        </property>
    </bean>

    <!--通过XML配置装配Bean:装配复杂集合-->
    <bean id="role1" class="com.ccff.spring.assembling.pojo.Role">
        <property name="roleId" value="1" />
        <property name="roleName" value="role-name-1" />
        <property name="roleNote" value="role-note-1" />
    </bean>
    <bean id="role2" class="com.ccff.spring.assembling.pojo.Role">
        <property name="roleId" value="2" />
        <property name="roleName" value="role-name-2" />
        <property name="roleNote" value="role-note-2" />
    </bean>
    <bean id="user1" class="com.ccff.spring.assembling.pojo.User">
        <property name="userId" value="1" />
        <property name="userName" value="user-name-1" />
        <property name="userNote" value="user-note-1" />
    </bean>
    <bean id="user2" class="com.ccff.spring.assembling.pojo.User">
        <property name="userId" value="2" />
        <property name="userName" value="user-name-2" />
        <property name="userNote" value="user-note-2" />
    </bean>
    <bean id="userRoleAssembly" class="com.ccff.spring.assembling.pojo.UserRoleAssembly">
        <property name="id" value="1" />
        <property name="list">
            <list>
                <ref bean="role1" />
                <ref bean="role2" />
            </list>
        </property>
        <property name="map">
            <map>
                <entry key-ref="role1" value-ref="user1" />
                <entry key-ref="role2" value-ref="user2" />
            </map>
        </property>
        <property name="set">
            <set>
                <ref bean="role1" />
                <ref bean="role2" />
            </set>
        </property>
    </bean>

    <!--通过命名空间装配Bean:简单的设值-->
    <bean id="role3" class="com.ccff.spring.assembling.pojo.Role" c:_0="3" c:_1="role-name-3" c:_2="role-note-3" />
    <bean id="role4" class="com.ccff.spring.assembling.pojo.Role" p:roleId="4" p:roleName="role-name-4" p:roleNote="role-note-4" />

    <!--通过命名空间装配Bean:为bean的属性设值-->
    <bean id="role5" class="com.ccff.spring.assembling.pojo.Role" c:_0="5" c:_1="role-name-5" c:_2="role-note-5" />
    <bean id="role6" class="com.ccff.spring.assembling.pojo.Role" p:roleId="6" p:roleName="role-name-6" p:roleNote="role-note-6" />
    <bean id="user3" class="com.ccff.spring.assembling.pojo.User" c:_0="3" c:_1="user-name-3" c:_2="user-note-3" />
    <bean id="user4" class="com.ccff.spring.assembling.pojo.User" p:userId="4" p:userName="user-name-4" p:userNote="user-note-4" />
    <util:list id="list">
        <ref bean="role5" />
        <ref bean="role6" />
    </util:list>
    <util:map id="map">
        <entry key-ref="role5" value-ref="user3" />
        <entry key-ref="role6" value-ref="user4" />
    </util:map>
    <util:set id="set">
        <ref bean="role5" />
        <ref bean="role6" />
    </util:set>
    <bean id="userRoleAssembly2" class="com.ccff.spring.assembling.pojo.UserRoleAssembly" p:id="2" p:list-ref="list" p:map-ref="map" p:set-ref="set" />

    <!--装配CompactDiscImpl,实现XML与注解的混合使用-->
    <bean id="compactDiscImpl" class="com.ccff.spring.assembling.service.CompactDiscImpl">
        <property name="title" value="七里香" />
        <property name="artist" value="周杰伦" />
    </bean>
    <bean id="cdPlayer" class="com.ccff.spring.assembling.pojo.CDPlayer">
        <property name="compactDisc" ref="compactDiscImpl" />
    </bean>
</beans>

  修改TestBean测试类,在该测试类中添加测试通过XML方式装配的测试方法TestBeanXML,具体代码如下所示:

package com.ccff.spring.assembling.test;

import com.ccff.spring.assembling.config.CDPlayerConfig;
import com.ccff.spring.assembling.pojo.CDPlayer;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值