前言:
Spring配置的可选方案 :
--隐式的bean发现机制和自动装配
--在Java中进行显式配置
--
在XML中进行显式配置
--构造器注入
--属性注入
以下内容摘自《Spring实战(第4版)》
2.4.1 创建XML配置规范
有@Configuration注解的类,而在XML配置中,这意味着要创建 一个XML文件,并且要以<beans>元素为根。
2.4.2 声明一个简单的<bean>
<bean class = "soundsystem.SgtPeppers" />
因为没有明确给定ID,所以这个bean将会根据全限定类名来进行命 名。在本例中,bean的ID将会 是“
soundsystem.SgtPeppers#0
”。
<bean id = "compactDisc" class = "soundsystem.SgtPeppers" />
单bean声明的一些特征 :
- 你不再需要直接负责创建SgtPeppers的实例,在基于JavaConfig的配置中,我们是需要这样做的。当Spring发 现这个<bean>元素时,它将会调用SgtPeppers的默认构造器来创 建bean。在XML配置中,bean的创建显得更加被动,不过,它并没有 JavaConfig那样强大,在JavaConfig配置方式中,你可以通过任何可以想象到的方法来创建bean实例。
- 在这个简单的<bean>声明中,我们将bean的类型以字符串的形式设置在了class属性中。谁能保证设置给class属性的值是真正的类呢?Spring的XML配置并不能从编译期的类型检查中受益。即便它所引用的是实际的类型,如果你重命名 了类,会发生什么呢?借助IDE检查XML的合法性使用能够感知Spring功能的IDE,如 Spring Tool Suite,能够在很大程度上帮助你确保Spring XML配置 的合法性。
2.4.3 借助构造器注入初始化bean
在Spring XML配置中,只有一种声明bean的方式:使用<bean>元素 并指定class属性。Spring会从这里获取必要的信息来创建bean。
在XML中声明DI时,会有多种可选的配置方案和风格。具体到 构造器注入,有两种基本的配置方案可供选择:
- <constructor-arg>元素
- 使用Spring 3.0所引入的c-命名空间
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="compactDisc" />
</bean>
作为替代的方案,你也可以使用Spring的c-命名空间。c-命名空间是 在Spring 3.0中引入的,它是在XML中更为简洁地描述构造器参数的 方式。要使用它的话,必须要在XML的顶部声明其模式,如下所示:
<?xml version="1.0" encoding="UTF-8">
<beans xmlns="
http://www.springframework.org/schema/beans";
xmlns:c="
http://ww.springframework.org/schema/c";
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance";
xsi:schemaLocation="
http://www.springframework.org/schema/beans
<beans>
<bean id = "CDPlayer" class="soundsystem.CDPlayer"
c:cd-ref="compactDisc" />
</bean>
c : cd -ref= "compactDisc"
c-命名空间前缀 构造器参数名 注入bean引用 要注入的bean的id
属性名以“c:”开头,也就是命名空间的前缀。接下来就是要装配的构 造器参数名,在此之后是“-ref”,这是一个命名的约定,它会告诉 Spring,正在装配的是一个bean的引用,这个bean的名字 是compactDisc,而不是字面量“compactDisc”。
引用参数的名称看起来有些怪 异,因为这需要在编译代码的时候,将
调试标志(debug symbol)保存在类代码中。如果你优化构建过程,将调试标志移除掉,那么这种方式可能就无法正常执行了。
替代的方案是我们使用参数在整个参数列表中的位置信息:
<bean id="cdplayer" class="soundsystem.CDPlayer"
c:_0-ref="compactDisc" />
我们已经将引用装配到了其他的bean之中,接下来看一下如何将
字面量值(literal value)装配到构造器之中。
迄今为止,我们所做的DI通常指的都是
类型的装配——也就是将对象 的引用装配到依赖于它们的其他对象之中——而有时候,我们需要做 的只是用一个字面量值来配置对象。
package soundsystem;
public class BlackDisc implements Compactisc
{
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);
}
}
<bean id="compactDisc" class="soundsystem.BlankDisc">
<constructor-arg value = "Sgt. Pepper's Lonely Hearts Club Band" />
<constructor-arg value = "The Beatles" />
</bean>
<bean id="compactDisc" class="soundsystem.BlankDisc"
c:_title="Sgt. Pepper's Lonely Hearts Club Band"
c:_artist="The Beatles" />
<bean>
<bean id="compactDisc" class="soundsystem.BlankDisc"
c:_0="Sgt. Pepper's Lonely Hearts Club Band"
c:_1="The Beatles" />
<bean>
装配集合
package soundsystem.collection;
import java.util.List;
import soundsystem.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);
}
}
}
在声明bean的时候,我们必须要提供一个
磁道列表
<bean id = "compactDisc" class="soundsystem.BlankDisc">
<constructor-arg value="Sgr. Pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
<constructor-arg><null/></constructor-arg>
</bean>
<null/>元素所做的事情与你的期望是一样的:将null传递给构造 器。这并不是解决问题的好办法,但在注入期它能正常执行。当调 用play()方法时,你会遇到NullPointerException异常,因此 这并不是理想的方案。
<bean id="compactDisc" class="soundsystem.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>Fixing a Hole</value>
</list>
</constructor-arg>
</bean>
public Discography(String artist, List<CompactDisc> cds) {...}
<bean id = "beatlesDiscography" class="soundsystem.Discography">
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<ref bean = "sgtPeppers" />
<ref bean = "whiteAlbum" />
<ref bean = "hardDaysNight" />
<ref bean = "revolver" />
...
</list>
</constructor-arg>
</bean>
<bean id = "beatlesDiscography" class="soundsystem.Discography">
<constructor-arg value="The Beatles" />
<constructor-arg>
<set>
<ref bean = "sgtPeppers" />
<ref bean = "whiteAlbum" />
<ref bean = "hardDaysNight" />
<ref bean = "revolver" />
...
</set>
</constructor-arg>
</bean>
在装配集合方面,<constructor-arg>比c-命名空间的属性更有优 势。目前,使用c-命名空间的属性无法实现装配集合的功能。
2.4.4 设置属性
Spring XML实现属性注入:
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import soundsystem.CompactDisc;
import soundsystem.MediaPlayer;
public class CDPlayer implements MediaPlayer
{
private CompactDisc compactDisc;
@Autowired
public void setCompactDisc(CompactDisc compactDisc)
{
this.compactDisc = compactDisc;
}
public void play()
{
compactDisc.play();
}
}
<bean id = "cdPlayer" class="soundsystem.CDPlayer">
<property name = "compactDisc" ref="compactDisc" />
</bean>
<property>元素为属性的Setter方法所提供的功能与<constructor-arg>元素为构造器所提供的功能是一样的。
Spring为<constructor-arg>元素提供了c-命名空 间作为替代方案,与之类似,Spring提供了更加简洁的p-命名空间, 作为<property>元素的替代方案。为了启用p-命名空间,必须要在 XML文件中与其他的命名空间一起对其进行声明:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="
http://www.springframework.org/schema/beans"
xmlns:p="
http://www.springframework.org/schema/p"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
...
</bean>
<bean id = "CDPlayer" class="soundsystem.CDPlayer"
p:compactDIsc-ref = "compactDisc" />
p: compactDIsc -ref = "compactDisc"
p-命名空间前缀 属性名 注入bean引用 注入id
将字面量注入到属性中
package soundsystem;
import java.util.List;
import soundsystem.CompactDisc;
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);
}
}
}
<bean id = "compactDisc" class = "soundsystem.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>
...
</list>
</property>
</bean>
or
<bean id = "compactDisc" class = "soundsystem.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>
...
</list>
</property>
</bean>
我们
不能使用p-命名空间来装配集合,没有便利的方式使用p-命名空间来指定一个值(或bean引用)的列表。但是,我 们可以使用
Spring util-
命名空间中的一些功能来简 化BlankDiscbean。
在XML中声明util-命名空间及其模式:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="
http://www.springframework.org/schema/beans"
xmlns:p="
http://www.springframework.org/schema/p"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
>
...
</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>
</utli:list>
<bean id="compactDisc"
class="soundsystem.BlankDisc
p:title="Sgt. Pepper's Lonely Hearts Club Band"
p:artist="The Beatles"
p:tracks-ref="trackList" />
Spring 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,其中包含值或引用
|