Spring In Action 学习 第二章 装配Bean

Spring配置的三种装配机制:

1. 在XML中进行显示配置。

2. 在Java中进行显示配置。

3. 隐式的bean发现机制和自动装配。

Spring实现自动化装配的方式:

1. 组件扫描: Spring会自动发现应用上下文中所创建的bean。

2. 自动装配: Spring自动满足bean之间的依赖。

练习源码 1. CD接口 CompactDisc.java

package org.yuanbin.soundsystem;

/**
 * CD接口
 * 
 * @author huang-yuanbin
 *
 */
public interface CompactDisc {
	void play();
}

练习源码 2. 实现CD接口 SgtPeppers.java

package org.yuanbin.soundsystem;

import org.springframework.stereotype.Component;

/**
 * 实现CompactDisc接口
 * 
 * @author huang-yuanbin
 *
 */
@Component
public class SgtPeppers implements CompactDisc {
	private String title = "伟大的渺小";
	private String artist = "林俊杰";

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

}

@Component 声明该类会作为组件类。

练习源码 3. 配置类(@ComponentScan注解) CDPlayerConfig.java

package org.yuanbin.soundsystem;

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

/**
 * 配置类
 * 
 * @author huang-yuanbin
 *
 */
@Configuration
@ComponentScan
public class CDPlayerConfig {

}

@ComponentScan 默认会扫描与配置类相同的包 ,查找带有@Component注解的类,并且会在Spring中自动为其创建一个bean。

练习源码 4 配置类(XML组件扫描)soundsConfig.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<context:component-scan base-package="org.yuanbin.soundsystem"></context:component-scan>

</beans>

练习源码 5 测试类 CDPlayerTest.java

package org.yuanbin.soundsystem;

import static org.junit.Assert.assertNotNull;

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 = CDPlayerConfig.class)
public class CDPlayTest {
	@Autowired
	private CompactDisc cd;

	@Test
	public void cdshouldNotBeNull() {
		// 判断cd属性不为null
		assertNotNull(cd);
	}
}

2.2.2 为组件扫描的bean命名

Spring应用上下文中所有的bean都会给定一个ID。如Spring给SgtPeppers指定一个ID为sgtPeppers,也就是将类名的第一个字母变成小写。

如果想为这个bean设置不同的ID,方法如下

@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc{
...
}

另一种方法是通过@Named注解

@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc{
...
}

2.2.3设置组件扫描的基础包

@Components 默认会以配置类所在的包作为基础包(base package)来扫描组件。

如果想扫描不同的包,方法如下:

@Configuration
@ComponentScan("com.yuanbin.soundsystem")
public class CDPlayerConfig{}

如果想更加清晰地表明你所设置的是基础包:

@Configuration
@ComponentScan(basePackages="com.yuanbin.soundsystem")
public class CDPlayerConfig{}

如果想设置多个基础包:

@Configuration
@ComponentScan(basePackages={"com.yuanbin.soundsystem","com.yuanbin.video"})
public class CDPlayerConfig{}

如果想指定包中所包含的类或接口:

@Configuration
@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
public class CDPlayerConfig{}

2.2.4 通过为bean添加注解实现自动装配

自动装配就是让Spring自动满足bean依赖的一种方法,会在Spring应用上下文中寻找匹配某个bean需求的其他的bean

练习源码 6. MediaPlayer接口

package org.yuanbin.soundsystem;

/**
 * MediaPlayer接口
 * 
 * @author huang-yuanbin
 *
 */
public interface MediaPlayer {
	void play();
}

练习源码 7.MediaPlayer实现类

@Autowired注解: 表明当Spring创建CDPlayer bean的时候,会通过这个构造器进行实例化并传入一个可设置给CompactDisc类型的bean。

package org.yuanbin.soundsystem;

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

/**
 * MediaPlayer实现类
 * 
 * @author huang-yuanbin
 *
 */
@Component
public class CDPlayer implements MediaPlayer {
	private CompactDisc cd;

	@Autowired
	public CDPlayer(CompactDisc cd) {
		// TODO Auto-generated constructor stub
		this.cd = cd;
	}

	public void play() {
		// TODO Auto-generated method stub
		cd.play();
	}

}

@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上,比如说,如果CDPlayer有一个setCompactDisc()方法,那么可以采用如下的注解形式进行自动装配:

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

在Spring初始化bean之后,它会尽可能得去满足bean的依赖,在本例中,依赖是通过带有@Autowired注解的方法进行声明的。

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属性设置为false:

@Autowired(required =false)
public void setCompactDisc(CompactDisc cd){
    this.cd =cd;
}

将required属性设置为false时,Spring会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状态。但是,将required属性设置为false时,你需要谨慎对待。如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性有可能会出现NullPointerException。

如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行自动装配

另一种装配方法是使用@ Inject注解

package org.yuanbin.soundsystem;
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class CDPlayer{
...

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

练习源码 8.验证自动装配

添加System Rules库依赖

<dependency>
    <groupId>com.github.stefanbirkner</groupId>
	<artifactId>system-rules</artifactId>
	<version>1.16.0</version>
</dependency>
package org.yuanbin.soundsystem;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

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

@SuppressWarnings("deprecation")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayTest {
	@Rule
	public final StandardOutputStreamLog log = new StandardOutputStreamLog();
	@Autowired
	private MediaPlayer Player;
	@Autowired
	private CompactDisc cd;

	@Test
	public void cdshouldNotBeNull() {
		// 判断cd属性不为null
		assertNotNull(cd);
	}

	@Test
	public void play() {
		Player.play();
		assertEquals("Playing 告白气球 by 周杰伦", log.getLog());
	}
}

2.3 通过Java代码装配bean

尽管很多场景下通过组件扫描和自动装配实现Spring的自动装配是更为推荐的方式,但有时自动化配置的方案行不通,因此需要明确配置Spring。比如说,你想要将第三方库的组件装配搭配到你的应用中,这种情况下,是没有办法在它的类上添加@Component 和@Autowired注解的,只能采用显示转配的方式。显示装配有两种方案: java和XML。在进行显示装配时,JavaConfig有更好的方案,因为他更为强大,类型安全并且对重构友好。

javaConfig是配置代码,这意味着它不应该包含任何业务逻辑,javaConfig也不应该侵入业务逻辑代码之中。尽管不是必须的,但通常将javaConfig放在单独的包中,使它与其他的应用程序逻辑分离开来,这样对它的意图就不会产生困惑了。

练习源码 9.  SgtPeppers类移除@Component注解

package org.yuanbin.soundsystem;

/**
 * 实现CompactDisc接口
 * 
 * @author huang-yuanbin
 *
 */
public class SgtPeppers implements CompactDisc {
	private String title = "伟大的渺小";
	private String artist = "林俊杰";

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

}

练习源码10. 声明一个简单的bean

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

@Bean表明这个方法会创建一个bean实例并将其注册到Spring应用上下文中。

默认情况下,bean的ID与带有@Bean注解的方法名是一样的。在本例中,bean的名字将会是sgtPeppers。如果想设置成一个不同的名字,可通过name属性指定一个不同的名字

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

 练习源码 11. 配置类

package org.yuanbin.soundsystem;

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

/**
 * 配置类
 * 
 * @author huang-yuanbin
 *
 */
@Configuration
public class CDPlayerConfig {
	@Bean
	public CompactDisc sgtPeppers() {
		return new SgtPeppers();
	}
	@Bean
	public CDPlayer cdPlayer(CompactDisc compactDisc) {
		return new CDPlayer(compactDisc);
	}
}

在这里,cdPlayer()方法请求一个CompactDisc作为参数。当Spring调用cdPlayer()创建CDPlayer bean的时候,它会自动装配一个CompactDisc到配置方法之中。然后,方法体就可以按照合适的方式来使用它。借助这种技术,cdPlayer()方法也能将CompactDisc注入到CDPlayer的构造器中,而且不用明确引用CompactDisc的@Bean方法

通过这种方式引用其他的bean通常是最佳的选择,因为它不会要求将CompactDisc声明到同一个配置类之中。在这里甚至没有要求CompactDisc必须要在JavaConfig中声明,实际上它可以通过组件扫描功能自动发现或者通过XML来配置。你可以将配置分散到多个配置类,XML文件以及自动扫描和装配bean之中,只要功能完整健全即可,不管CompactDisc是采用什么方式创建出来的,Spring都会将其传入到配置方法中,并用来创建CDPlayer bean。

默认情况下,Spring中的bean都是单例的,我们没有必要为第二个CDPlayre bean创建完全相同的SgtPeppers实例,所以,Spring会拦截对sgtPeppers()的调用并确保返回的是Spring所创建的bean,也就是Spring本身在调用sgtPeppers()时所创建的CompactDiscbean。因此,两个CDPlayer bean会得到相同的SgtPeppers实例。

2.4.1创建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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

</beans>

2.4.2 声明一个简单的bean

<bean class="org.yuanbin.soundsystem.SgtPeppers"></bean>

<bean>元素类似于JavaConfig中的@Bean注解

因为没有,明确给定ID,所以这个bean将会根据全限定类名进行命名。在本例中·bean的ID将会是“org.yuanbin.soundsystem.SgtPeppers#0”。其中“#0”是一个计数的形式,用来区分相同类型的其他bean。如果你声明了另外一个SgtPeppers,并且没有明确进行标识,那么它会自动得到的ID为“org.yuanbin.soundsystems.SgtPeppers#1”

如果想设置ID

<bean id="compactDisc" class="org.yuanbin.soundsystem.SgtPeppers"></bean>

 2.4.3 借助构造器注入初始化bean

<bean id="cdPlayer" class="org.yuanbin.soundsystem.CDPlayer">
    <constructor-arg ref="compactDisc"/>
</bean>

 当Spring遇到这个<bean>元素时,它会创建一个CDPlayer实例。<constructor-arg>元素会告知Spring要将一个ID为compactDisc的bean的引用传递到CDPlayer的构造器中。

替代方案,可使用Spring的c-命名空间。使用它的话,必须要在XML的顶部声明其模式

xmlns:c="http://www.springframework.org/schema/c"

在c-命名空间和模式声明之后,我们就可以使用它来声明构造器参数了

<bean id="cdPlayer" class="org.yuanbin.soundsystem.CDPlayer"
		c:cd-ref="compactDisc"></bean>

 "c:" 命名空间的前缀 "cd" 构造器参数名 "-ref" 注入bean引用 "compactDisc" 要注入的bean的ID

替代方案是使用参数在整个参数列表中的位置信息:

<bean id="cdPlayer" class="org.yuanbin.soundsystem.CDPlayer"
		c:_0-ref="compactDisc"></bean>

因为在XML中不允许数字作为属性的第一个字符,因此必须添加一个下画线作为前缀。

将字面量注入到构造器中

练习源码12. 创建CompactDisc的新的实现

package org.yuanbin.soundsystem;

public class BlankDisc implements CompactDisc {
	private String title;
	private String artist;

	@Override
	public void play() {
		// TODO Auto-generated method stub
		System.out.println("Playing " + title + " by " + artist);
	}

	public BlankDisc(String title, String artist) {
		// TODO Auto-generated constructor stub
		this.title = title;
		this.artist = artist;
	}

}

在SgtPeppers中,唱片名称和艺术家的名字都是硬编码,但是这个CompactDisc实现类不同,它更加灵活。像现实中的空磁盘一样,它可以设置成任意你想要的艺术家和唱片的名称,现在我们可以将已有的SgtPeppers替换为这个类。

修改配置类

<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc">
    <constructor-arg value="告白气球"/>
    <constructor-arg value="周杰伦"/>
</bean>

使用<constructor-arg>元素进行构造器参数的注入,使用value属性,表明给定的值要以字面量的形式注入到构造器中。

如果使用c命名空间

<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc"
    c:_title="告白气球"
    c:_artist="周杰伦"> 
</bean>

还可以通过参数索引装配相同的字面量值

<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc"
    c:_0="告白气球"
    c:_1="周杰伦"> 
</bean>

XML不允许某个元素的多个属性具有相同的名字。因此,如果有两个或更多的构造器参数的话,我们不能简单地使用下划线进行标示。但是如果只有一个构造器参数的话,我们就可以这样做。假设BlandkDisc只有一个构造参数。

<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc"
    c:_="告白气球"> 
</bean>

 装配集合

练习源码 13.为BlankDisc添加磁道列表

package org.yuanbin.soundsystem;

import java.util.List;

public class BlankDisc implements CompactDisc {
	private String title;
	private String artist;
	private List<String> tracks;

	@Override
	public void play() {
		// TODO Auto-generated method stub
		System.out.println("Playing " + title + " by " + artist);
		for (String track : tracks) {
			System.out.println("-Track:" + track);
		}
	}

	public BlankDisc(String title, String artist, List<String> tracks) {
		// TODO Auto-generated constructor stub
		this.title = title;
		this.artist = artist;
		this.tracks = tracks;
	}

}

在声明bean的时候,我们必须要提供一个磁道列表。

最简单的方法是将列表设置为null。因为它是一个构造器参数,所以必须要声明它。

<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc">
    <constructor-arg value="告白气球"/>
    <constructor-arg value="周杰伦"/>
    <constructor-arg><null/><constructor-arg>
</bean>

 将null传递给构造器,这并不能解决问题,但在注入期它能正常执行,当调用play()方法时,你会遇到NullPointerException异常。更好的解决方案是提供一个磁道名称的列表:

练习源码 14.配置类添加列表

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc">
		<constructor-arg value="告白气球"></constructor-arg>
		<constructor-arg value="周杰伦"></constructor-arg>
		<constructor-arg>
			<list>
				<value>塞纳河畔 左岸的咖啡</value>
				<value>我手一杯 品尝你的美</value>
				<value>留下唇印的嘴</value>
			</list>
		</constructor-arg>
	</bean>	
</beans>

<list>元素是<constructor-arg>的子元素,表明一个包含值的列表将会传递到构造器中,其中,<value>元素用来指定列表中的每一个元素。

与之类似,我们也可以使用<ref>元素代替<value>,实现bean引用列表的装配。例如,假设你有一个Discography类,它的构造器如下所示:

public Discography(String artist, List<CompactDisc> cds){...}

 那么,你可以采取如下的方式配置Discography 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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<bean id="compactDisc" class="org.yuanbin.soundsystem.Discography">
		<constructor-arg value="告白气球"></constructor-arg>
		<constructor-arg value="周杰伦"></constructor-arg>
		<constructor-arg>
			<list>
				<ref bean="sgtPeppers"/>
				<ref bean="whiteAlbum"/>
				<ref bean="revolver"/>
                ...
			</list>
		</constructor-arg>
	</bean>	
</beans>

 当参数的类型是List时,使用<list>元素是合情合理的。尽管也可以按同样的方式使用<set>元素

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc">
		<constructor-arg value="告白气球"></constructor-arg>
		<constructor-arg value="周杰伦"></constructor-arg>
		<constructor-arg>
			<set>
				<value>塞纳河畔 左岸的咖啡</value>
				<value>我手一杯 品尝你的美</value>
				<value>留下唇印的嘴</value>
			</set>
		</constructor-arg>
	</bean>	
</beans>

 使用<set>元素的话,重复的值都会被忽略掉,存放顺序也不会得到保障。

在装配集合方面,<constructor-arg>比c-命名空间的属性更有优势,目前使用c-命名空间的属性无法实现装配集合的功能。

2.4.4设置属性

使用Spring XML实现属性注入。假设属性注入的CDplayer如下所示

package org.yuanbin.soundsystem;

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

/**
 * MediaPlayer实现类
 * 
 * @author huang-yuanbin
 *
 */
@Component
public class CDPlayer implements MediaPlayer {
	private CompactDisc cd;

	@Autowired
	public void setCompactDisc(CompactDisc compactDisc){
        this.compactDisc =compactDisc;
    }

	public void play() {
		// TODO Auto-generated method stub
		cd.play();
	}

}

现在,CDPlayer没有任何的构造器,它也没有任何的强依赖。因此,你可以采用如下的方式将其声明为Spring bean;

<bean id="cdPlayer" class="org.yuanbin.soundsystem.CDPlayer">
</bean>

 Spring在创建bean的时候不会有任何问题,但是CDPlayerTest会因为出现NullPointerException而导致测试失败,因为我们并没有注入CDPlayer的compactDisc属性。不过,按照如下方式修改XML,就能解决该问题:

<bean id="cdPlayer" class="org.yuanbin.soundsystem.CDPlayer">
    <property name="compactDisc" ref="compactDisc"/>
</bean>

<property>元素为属性的Setter方法所提供的功能与<constructor-arg>元素为构造 器所提供的功能是一样的。在本例中,它引用了ID为compactDisc的bean(通过ref属性),并将其注入到compactDisc属性中(通过setCompactDisc()方法)

p-命名空间是Spring为<property>元素提供的替代方案

启动p-命名空间,必须要在XML文件中与其他的命名空间一起对其进行声明:

xmlns:p="http://www.springframework.org/schema/p"

 我们可以使用p-命名空间,按照以下的方式装配compactDisc属性:

<bean id="cdPlayer" class="org.yuanbin.soundsystem.CDPlayer"
    p:compactDisc-ref="compactDisc">
</bean>

"p:"p-命名空间前缀 "compactDisc-ref":属性名 "-ref" 注入bean引用 "compactDisc"所注入bean的ID

练习源码 15.修改BlankDisc类

package org.yuanbin.soundsystem;

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;
	}

	@Override
	public void play() {
		// TODO Auto-generated method stub
		System.out.println("Playing " + title + " by " + artist);
		for (String track : tracks) {
			System.out.println("-Track:" + track);
		}
	}
}

练习源码 16.修改配置类

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc">
		<property name="title" value="告白气球"></property>
		<property name="artist" value="周杰伦"></property>
		<property name="tracks">
			<list>
				<value>塞纳河畔 左岸的咖啡</value>
				<value>我手一杯 品尝你的美</value>
				<value>留下唇印的嘴</value>
			</list>
		</property>
	</bean>
</beans>

 另一种可选方案就是使用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:c="http://www.springframework.org/schema/c"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc">
        p:title="告白气球"
        p:artist="周杰伦"
		<property name="tracks">
			<list>
				<value>塞纳河畔 左岸的咖啡</value>
				<value>我手一杯 品尝你的美</value>
				<value>留下唇印的嘴</value>
			</list>
		</property>
	</bean>
</beans>

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

首先需声明util-命名空间及其模式:

xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation ="http://www.springframework.org/schema/util
                     http://www.springframework.org/schema/util/spring-util.xsd"

util-命名空间所提供的功能之一就是<util:list>元素,它会创建一个列表的bean。借助<util:list>,我们可以将磁道列表转移到BlankDisc bean之外,并将其声明到单独的bean之中。

<util:list id="trackList">
    <value>塞纳河畔 左岸的咖啡</value>
	<value>我手一杯 品尝你的美</value>
	<value>留下唇印的嘴</value>
</util:list>

现在,我们能够像使用其他的bean那样,将磁道列表bean注入到BlankDisc bean的track属性中:

<bean id="compactDisc" class="org.yuanbin.soundsystem.BlankDisc">
        p:title="告白气球"
        p:artist="周杰伦"
        p:tracks-ref ="trackList" />
元素描述
<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,其中包含值或引用

 

 

 

 

 

 

 

 

 2.5导入和混合配置

2.5.1在JavaConfig中引用XML配置

package org.yuanbin.soundsystem;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDConfig {
	@Bean
	public CompactDisc sgtPeppers() {
		return new SgtPeppers();
	}
}
package org.yuanbin.soundsystem;

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 CDPlayer cdPlayer(CompactDisc compactDisc) {
		return new CDPlayer(compactDisc);
	}
}
package org.yuanbin.soundsystem;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({CDConfig.class,CDPlayerConfig.class)
public class SoundSystemConfig {
	...
}

 

package org.yuanbin.soundsystem;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({CDConfig.class,CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {
	...
}

 2.5.2在XML中引用JavaConfig配置

<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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <bean class="org.yuanbin.soundsystem.CDConfig"/>
	<bean id="cdPlayer" class="org.yuanbin.soundsystem.CDPlayer" c:cd-ref="compactDisc"/>
</beans>
<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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <bean class="org.yuanbin.soundsystem.CDConfig"/>
    <import resource="cdplayer-config.xml"/>
</beans>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值