Spring-2.装配

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

  1. 自动化装配Bean
  2. 通过Java进行显式配置
  3. 在XML中进行配置

1.自动化装配bean

Spring从两个方面来实现自动化装配:

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

以下以一个CD播放器的概念展现自动化装配bean的过程

1.1 创建可被发现的bean

用CompactDisc接口定义CD的概念

package com.junzerg.player_autoconfig;

public interface CompactDisc {
    void play();
}

1.2 带有@Component注解的CompactDisc实现类SgtPeppers

package com.junzerg.player_autoconfig;

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

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

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

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

}
  1. @Component注解
    • @Component注解表明该类会作为组件类,并告知Spring要为这个类创建bean
    • 默认bean的ID名为类名首字母变成小写,可以通过@Component为bean设置自定义ID: @Component("theId")
  2. @Autowired注解声明自动装配,该注解可以用在类的任何方法,主要是构造器方法,和Setter方法上。Spring都会尝试满足方法参数上所声明的依赖。
    • 如果有一个bean匹配依赖需求,这个bean会被装配进来
    • 如果没有匹配的bean,在应用文创建的时候,Spring会抛出一个异常。可以通过设置@AutoWired注解的required属性值为false来避免异常的出现。这时,Spring尝试执行自动装配,但是如果没有匹配的bean,Spring会让这个bean处于未装配的状态,有可能出现NullPointerException异常。
    • 如果有多个bean能满足依赖关系,Spring会抛出一个异常,这里可以添加一个自动装配的选择范围。
    • @Autowired是Spring特有的注解,可以替换为Java注解中的@Injection。

1.3 配置Spring,使其寻找带有@Component注解的类,并为其创建bean。

  1. 通过Java代码中使用@ComponentScan注解,启动组件扫描
    • 默认用配置类所在的包作为基础包(base package)来扫描组件
    • 用value属性来指定不同的基础包:@ComponentScan("soundsystem")
    • 通过basePackages属性更加清晰地指明基础包:@Component(basePackages="soundsystem")
    • 将basePackages属性设置为一个数组来设置多个基础包:@Component(basePackages={"soundsystem", "video"})
    • 可以指定为包中所含的类或者接口:@Component(basePackagesClasses=CDPlayer.class. DVDPlayer.class)
package com.junzerg.player_autoconfig.config;

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

@Configuration
@ComponentScan("com.junzerg.player_autoconfig")
public class CDPlayerConfig {
}
  1. 在XML配置方法中,<context:component-scan>元素可以有对应的属性和子元素。
<?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"
    xmlns:c="http://www.springframework.org/schema/c" xmlns:p="http://www.springframework.org/schema/p"
    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">

    <context:component-scan base-package="com.junzerg.player_autoconfig" />

</beans>

1.4 测试

  1. 测试通过Java配置的
package com.junzerg.player_autoconfig;

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
//import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
import org.junit.contrib.java.lang.system.SystemOutRule;
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;

import com.junzerg.player_autoconfig.config.CDPlayerConfig;

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

    @Rule
    public final SystemOutRule log = new SystemOutRule().enableLog();

    @Autowired
    private MediaPlayer player;

    @Autowired
    private CompactDisc cd;

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

    @Test
    public void play() {
        player.play();
        assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n", log.getLog());
    }

}
  1. 测试通过XML配置的
package com.junzerg.player_autoconfig;

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemOutRule;
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(locations = "classpath:META-INF/spring/soundsystem.xml")
public class CDPlayerXMLConfigTest {

    @Rule
    public final SystemOutRule log = new SystemOutRule().enableLog();

    @Autowired
    private MediaPlayer player;

    @Autowired
    private CompactDisc cd;

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

    @Test
    public void play() {
        player.play();
        assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n", log.getLog());
    }

}
  1. 测试结果

Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles

2. 通过Java代码配置bean

  • 和xml相比,JavaConfig是更好的方案
  • JavaConfig是配置代码,不应该包含任何的业务逻辑,也不应该侵入到业务代码中
  • 通常会把JavaConfig放到单独的包中,使它与其他的业务逻辑分开

2.1 创建配置类

通过@Configuration租借表明类是配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。 注意和上一节相比,移除了@ComponentScan注解。

package com.junzerg.player_javaconfig.config;

import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
}

2.2 声明简单的bean

在JavaConfig中编写方法,创建所需类型的实例,为方法添加@Bean注解。将会把方法返回的对象注册为Spring应用上下文中的bean。 如下代码声明了CompactDisc bean:

@Bean
public CompactDisc sgtPeppers() {
    return new SgtPeppers();
}

@Bean表示这个方法将返回一个要注册为Spring应用上下文的bean。方法体中是产生这个bean实例的逻辑。

默认情况下 ,bean的ID和@Bean注解的方法名相同。如下代码可以指定一个不同的名字:

@Bean(name="theSgtPeppers"
public CompactDisc sgtPeppers(){
    return new SgtPeppers();
}

在Java描述中,可以发挥Java的所有功能,只要最终产生的是一个CompactDisc实例。如下代码可以随机选择一个CompactDisc播放:

@Bean
public CompactDisc randomBeatlesCD() {
    int choice = (int) Math.floor(Math.random() * 4);
    if(choice == 0) {
        return new SgtPeppers();
    }
    else if(choice == 1) {
        return new WhiteAlbum();
    }
    else if(choice == 2) {
        return new HardDaysNight();
    }
    else {
        return new Revolver();
    }
}

2.3 用JavaConfig实现注入

在JavaConfig中装配bean的最简单的方式就是引用创建bean的方法。如下方法声明一个CDPlayer

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

在使用了@Bean注解后,表明这个方法创建一个ID为cdPlayer的bean实例并注册到Spring应用上下文中。 但是cdPlayer()方法和前文sgtPepper()方法区别在于没有使用默认的构造器实例,而是需要传入CompactDisc对象的构造器来创建CDPlayer实例。添加@Bean之后,Spring会拦截所有对它的调用,并确保该方法所创建的bean,而不是每次都对其进行直接的调用。 例如如下代码会得到相同的SgtPepper实例:

@Bean
public CDPlayer cdPlayer(){
    return new CDPlayer(sgtPepper());
}
@Bean
public CDPlayer anotherCDPlayer(){
    return new CDPlayer(sgtPepper());
}

通过如下方法是引用其他bean的最佳选择:

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

在Sring调用cdPlayer()创建CDPlayer bean 的时候,它会自动装配一个CompactDisc到装配方法中,然后方法体可以按照合适的方法来使用它。它可以通过组件扫描功能或XML来配置,只要功能健全,不管CompactDisc用什么方式创建的,Spring都会将其传入到配置方法中,来创建CDPlayer bean。

因此注意:带有@Bean注解的方法可以采用任何必要的Java功能来产生bean实例。

2.4 测试

  1. 装配文件为:
package com.junzerg.javaconfig;

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

@Configuration
public class CDPlayerConfig {

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

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

}
  1. SgtPeppers.java
package com.junzerg.javaconfig;

public class SgtPeppers implements CompactDisc {

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

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

}
  1. 测试类
package com.junzerg.javaconfig;

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemOutRule;
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 = CDPlayerConfig.class)
public class CDPlayerTest {

    @Rule
    public final SystemOutRule log = new SystemOutRule().enableLog();

    @Autowired
    private MediaPlayer player;

    @Test
    public void play() {
        player.play();
        assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n", log.getLog());
    }

}
  1. 测试结果

Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles

3. 通过XML装配

3.1 创建XML配置规范

类似于使用JavaConfig要创建一个嗲有@Configuration注解的类,在XML配置中,要创建一个以<beans>元素为根的XML文件。 其基本结构如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  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/context 
    http://www.springframework.org/schema/context/spring-context.xsd">

<!-- configuration details go here -->

</beans>

3.2 声明简单的<bean>

类似于JavaConfig中的@Bean注解,在XML配置模式中要使用<bean>元素声明一个bean。如下代码声明了一个CompactDisc bean:

<bean class="com.junzerg. xmlconfig.SgtPeppers" />

创建这个bean的类通过class属性来指定,并且要使用全限定类名。

如果没有明确指定ID,bean会根据全限定类名来进行命名,上面代码中的bean的ID将会是"com.junzerg.xmlconfig.SgtPeppers#0"。#0用来区分相同类型的其他bean,如果声明另外一个没有明确标识的SgtPeppers,其ID将会是"com.junzerg.xmlconfig.SgtPeppoers#1"。

如下代码为bean指定ID:

<bean id="compactDisc" class="com.junzerg. xmlconfig.SgtPeppers" />

通过xml配置bean的一些特征:

  • 不需要直接负责创建SgtPeppers,Spring发现的<bean>元素会调用默认构造器。
  • bean类型是以字符串的形式设置在class属性中的。
    • 该值的正确性需要保证
    • 重命名类之后字符串需要修改

3.3 借助构造器注入初始化的bean

在XML中声明DI时,有两种配置方案可以选择:

  1. <constructor-arg>元素,会显得XML更冗长,但是能完成一些c-命名空间不能完成的工作。
  2. c-命名空间,简洁一些,但是功能有限

3.3.1 通过构造器注入bean引用

如下代码用元素的方式声明CDPlayer并通过ID引用StgPeppers:

<bean id="cdPlayer" class="com.junerg.xmlconfig.CDPlayer">
    <constructor-arg ref="compactDisc" />
</bean>

如下代码用命名空间的方式声明:

  • 在XML顶部声明其模式
  • 在<bean>标签中使用属性
<?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:c="http://www.springframework.org/schema/c"
    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="cdPlayer" class="com.junzerg.xmlconfig.CDPlayer" c:cd-ref="compactDisc" />
</beans>

c-命名空间的属性名组成含义为:

属性名组成含义

还可以在使用参数在整个参数列表中的位置信息:

<bean id="cdPlayer" class="com.junzerg.xmlconfig.CDPlayer" c:_0-ref="compactDisc">

如果只有一个构造器参数,还可以不用标示参数:

<bean id="cdPlayer" class="com.juznerg.xmlconfig.CDPlayer" c:_-ref="compactDisc">

3.3.2 将字面量注入到构造器中

可以用一个字面量值来配置对象。 例如如下所示的CompactDisc的实现:

package com.junzerg.xmlconfig;

public class BlankDisc implements CompactDisc {

    private String title;
    private String artist;

    public BlankDisc(String title, String artist) {
        this.title = title;
        this.artist = artist;
    }

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

}

这时需要同时修改xml配置:

  • 如果使用<constructor-arg>元素,使用value属性表明给定值用字面量的形式注入到构造器中:
<bean id="compactDisc" class="com.junzerg.xmlconfig.BlankDisc">
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
</bean>
  • 如果使用c-命名空间:
    1. 引用构造器参数的名字,去掉-ref后缀。
<bean id="compactDisc"
        class="com.junzerg.xmlconfig.BlankDisc"
        c:_title="Sgt. Pepper's Lonely Hearts Club Band"
        c:_artist="The Beatles" />
  1. 使用参数索引
<bean id="compactDisc"
        class="com.junzerg.xmlconfig.BlankDisc"
        c:_0="Sgt. Pepper's Lonely Hearts Club Band"
        c:_1="The Beatles" />
  1. 如果只有一个构造器参数,可以使用如下方式:
<bean id="compactDisc"
        class="com.junzerg.xmlconfig.BlankDisc"
        c:_="Sgt. Pepper's Lonely Hearts Club Band" />

3.3.3 装配集合

如果构造器参数中有列表或者集合, 也需要装配进去,例如如下实现:

package com.junzerg.xmlconfig.collections;

import java.util.List;
import com.junzerg.xmlconfig.CompactDisc;

public class BlankDisc implements CompactDisc {

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

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

    public void play() {
        System.out.println("Playing " + title + " by " + artist);
        for (String track : tracks) {
            System.out.println("-Track: " + track);
        }
    }

}

为了提供列表作为构造器参数,有以下方法:

  • 最简单的方式就是使用null作为列表参数,注意需要使用<null />元素
<bean id="compactDisc" class="com.junzerg.xmlconfig.BlankDisc">
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
    <constructor-arg><null /></constructor-arg>
</bean>
  • 更好的方法是提供列表或集合参数
    1. 使用<list>元素作为<constructor-arg>的子元素,<value>元素来制定列表列表中的每个元素:
<bean id="compactDisc" class="com.junzerg.mixedconfig.BlankDisc"
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
    <constructor-arg>
        <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>
            <!-- ...other tracks omitted for brevity... -->
        </list>
    </constructor-arg>
</bean>
  1. 使用ref元素代替<value>实现。
<bean id="compactDisc" class="com.junzerg.mixedconfig.Discography"
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
    <constructor-arg>
        <list>
          <ref bean="stgPeppers" />
          <ref bean="whiteAlbum" />
          <ref bean="hardDaysNight" />
          <ref bean="revolver" />
        </list>
    </constructor-arg>
</bean>
  1. <set>元素同样能被用来设置集合元素
<bean id="compactDisc" class="com.junzerg.mixedconfig.BlankDisc"
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
    <constructor-arg>
        <set>
            <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>
            <!-- ...other tracks omitted for brevity... -->
        </set>
    </constructor-arg>
</bean>

注意:

  1. 使用Set元素的话,所有重复的值都会被忽略,存放顺序也不会保证。
  2. c-命名空间不能 实现装配集合的功能。

3.3.4 设置属性

对于属性注入的如下类:

package com.junzerg.xmlconfig;

import org.springframework.beans.factory.annotation.Autowired;

public class CDPlayer implements MediaPlayer {
    private CompactDisc cd;

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

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

}

p.s:对强依赖使用构造器注入,对于可选依赖使用属性注入。

接下来对CDPlayer声明为Spring bean(需要property元素应用bean并通过setCompactDisc()方法注入到compactDisc属性中):

<bean id="cdPlayer" class="com.junzerg.xmlconfig.CDPlayer">
    <property name="compactDisc" ref="compactDisc" / >
</bean>

同<constructor-arg>元素可以用c-命名空间作为替代方案一样,property元素可以用p-命名空间作为替代方案:

  1. 在XML文件中对命名空间进行声明
  2. 使用p-命名空间对属性进行装配
<?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:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
     xsi:schemaLocation="http://www.springframework.org/schema/bean 
    http://www.springframework.org/schema/beans/spring-beans.xsd>

    <bean id="cdPlayer" class="com.junzerg.xmlconfig.properties.CDPlayer"
        p:compactDisc-ref="compactDisc" />

</beans>

p-命名空间属性的组成

  1. 属性名称用p:前缀,表明所设置的是一个属性
  2. 要注入的属性
  3. 属性名以-ref结尾,提示Spring要装配的是引用,而不是字面量

将字面量注入属性中

属性也可以注入字面量。例如如下Blank Disc类,不要求装配任何属性:

package com.junzerg.xmlconfig;

import java.util.List;

public class BlankDisc implements CompactDisc {

    private String title;
    private String artist;
    private List<String> tracks;
    
    public void setTitle(String title) {
        this.title = title;
    }
    
    public void setArtist(String artist) {
        this.artist = artist;
    }
    
    public void setTracks(List<String> tracks) {
        this.tracks = tracks;
    }
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
        for( String track : tracks) {
            System.out.println("-Track: " + track);
        }
    }

}

然后再借助<property>元素的value属性来进行属性装配:

<bean id="compactDisc" class="com.junzerg.xmlconfig.properties.BlankDisc">
    <property name="title" value="Sgt. Pepper's Lonely Hearts Club Band" />
    <property name="artist" value="The Beatles" />
    <property name="tracks">
        <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>
            <value>She's Leaving Home</value>
            <value>Being for the Benefit of Mr. Kite!</value>
            <value>Within You Without You</value>
            <value>When I'm Sixty-Four</value>
            <value>Lovely Rita</value>
            <value>Good Morning Good Morning</value>
            <value>Sgt. Pepper's Lonely Hearts Club Band Reprise)</value>
            <value>A Day in the Life</value>
        </list>
    </property>
</bean>

同样,也可以通过p-命名空间的属性来讲字面量注入,和c-命名空间一样的是,装备bean应用与装配字面量的唯一区别在于是否带有"-ref"后缀:

<bean id="compactDisc" class="com.junzerg.xmlconfig.properties.BlankDisc"
    p:title="Sgt. Pepper's Lonely Hearts Club Band"
    p:artist="The Beatles">
    <property name="tracks">
        <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>
            <value>She's Leaving Home</value>
            <value>Being for the Benefit of Mr. Kite!</value>
            <value>Within You Without You</value>
            <value>When I'm Sixty-Four</value>
            <value>Lovely Rita</value>
            <value>Good Morning Good Morning</value>
            <value>Sgt. Pepper's Lonely Hearts Club Band (Reprise)</value>
            <value>A Day in the Life</value>
        </list>
    </property>
</bean>

注意,不能使用p-命名空间来装配集合,没有便利方式使用p-命名空间来指定一个值(或者bean应用)的列表。但是可以使用-util-命名空间的一些功能来简化bean:

  1. 先在XML中声明util-命名空间及其模式:
<?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:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
    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">
    ...
</bean>
  1. 使用<util:list>元素,创建一个立标bean:
<util:list id="trackList">
    <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>
    <value>She's Leaving Home</value>
    <value>Being for the Benefit of Mr. Kite!</value>
    <value>Within You Without You</value>
    <value>When I'm Sixty-Four</value>
    <value>Lovely Rita</value>
    <value>Good Morning Good Morning</value>
    <value>Sgt. Pepper's Lonely Hearts Club Band (Reprise)</value>
    <value>A Day in the Life</value>
</util:list>
  1. 再将bean注入到需要引入的bean的tracks属性中:
<bean id="compactDisc" class="com.junzerg.xmlconfig.properties.BlankDisc"
    p:title="Sgt. Pepper's Lonely Hearts Club Band" 
    p:artist="The Beatles"
    p:tracks-ref="trackList" />

p.s.:还有可用的util-命名空间的成员如下:

元素

描述

<util:constant>

引用某个类型的public static域,并将其暴露为bean

util:list

创建一个java.util.List类型的bean,其中包含值或者引用

util:map

创建一个java.util.Map类型的bean,其中包含值或者引用

util:properties

创建一个java.util.Properties类型的bean

util:property-path

创建一个bean的属性(或者内嵌属性)并将其暴露为bean

util:set

创建一个java.util.Set类型的bean,其中包含值或者引用

4 导入和混合配置

4.1 在JavaConfig中引入XML配置

在JavaConfig中可以使用@import注解导入其他的JavaConfig,例如:

package com.junzerg.mixedconfig;

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

@Configuration
@Import(CDPlayerConfig.class)
public class SoundSystemConfig {
     @Bean
    public CDPlayer cdPlayer(CompactDisc cd){
        return new CDPlayer(cd);
    }
}

对于XML配置的BlankDisc: cd-config.xml

<bean id="compactDisc" class="com.junzerg.mixedconfig.BlankDisc"
    c:_0="Sgt. Pepper's Lonely Hearts Club Band" 
    c:_1="The Beatles">
    <constructor-arg>
        <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>
            <!-- ...other tracks omitted for brevity... -->
        </list>
    </constructor-arg>
</bean>

以及JavaConfig注解的CDPlayerConfig 那么可以用@ImportResource注解,将他们引入同一个JavaConfig:

package com.junzerg.mixedconfig;

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

@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {

}

4.2 在XML配置中引用JavaConfig

可以用<import>元素在XML中引入另外的xml配置文件:

<?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:c="http://www.springframework.org/schema/c"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd">

  <impport resource="cd-config.xml" />

  <bean id="cdPlayer"
        class="com.junzerg.mixedconfig.CDPlayer"
        c:cd-ref="compactDisc" />
        
</beans>

要将JavaConfig文件引入xml文件,可以直接使用<bean>元素:

<?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:c="http://www.springframework.org/schema/c"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean class="com.junzerg.mixedconfig.CDConfig" />

  <bean id="cdPlayer"
        class="com.junzerg.mixedconfig.CDPlayer"
        c:cd-ref="compactDisc" />
        
</beans>

5. 其他

5.1 本节使用了Spring的测试功能,因此要在Maven中添加Spring-test依赖

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

5.2 本节原例中的org.junit.contrib.java.lang.system.StandardOutputStreamLog需要在Maven中引入以下依赖

<dependency>
    <groupId>com.github.stefanbirkner</groupId>
    <artifactId>system-rules</artifactId>
    <version>1.16.1</version>
    <scope>test</scope>
</dependency>

另:原例中使用的StandardOutputStreamLog 包在最新的Junit中已经没有了,根据网上修改成以下,并修改相关用法:

import org.junit.contrib.java.lang.system.SystemOutRule;

@Rule
public final SystemOutRule log = new SystemOutRule().enableLog();

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java并发-19.Condition接口

    一般而言,都会将Condition变量作为成员变量。当调用await方法后,当前线程会释放锁并进入Condition变量的等待队列,而其他线程调用signal方...

    悠扬前奏
  • Java并发-10.等待/通知

    悠扬前奏
  • Spring-1.依赖注入(BI)和面向切面编程(AOP)

    通过依赖注入(Dependency Injection, DI),对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定。

    悠扬前奏
  • log4net记录日志到数据库自定义字段

    public string Mobiles { get; set; }

    guokun
  • 使用Topshelf部署Windows服务

    TopShelf支持使用Log4net,使用Nuget安装Topshelf.Log4Net:

    yaphetsfang
  • C# winform之Log4Net的使用

    当我们将asp程序部署到远程服务器上的时候,如果遇到程序错误,如何能快速的判断我们程序的错误呢。所以--> Log4Net作为记录日志的一大神器,不得不学会熟练...

    zls365
  • 通过正则表达式限制输入框只能数字,且不能以0开头

    最近在做项目的时候有个需求,输入框输入金额的。这个金额只能是整数,我们都知道金额肯定不能以0开头。

    Java旅途
  • AppScan安全漏洞说明及解决方案

    解决方案:向所有会话cookie 添加HttpOnly属性 ,可以在过滤器中统一添加。

    java乐园
  • lodash 是如何做类型检测的

    JS 的基本数据类型有 Number,String,Boolean,Symbol,Null,Undefined,六种数据类型。一种引用类型 object。

    Javanx
  • 高流量站点NGINX与PHP-fpm配置优化

    使用Nginx搭配PHP已有7年的这份经历让我们学会如何为高流量站点优化NGINX和PHP-fpm配置。 以下正是这方面的一些提示和建议: 1. 将TCP切换为...

    小小科

扫码关注云+社区

领取腾讯云代金券