推荐使用自动化配置和 JavaConfig,学习 XML 配置,只是为了帮助你维护已有的 XML 配置。
之前需要提前创建哪些具体的类,请参考前一篇:Spring 如何使用自动化装配 bean?
Q:如何通过 XML 显示的配置 Spring?
A:①、创建 XML 配置规范
在使用 JavaConfig 时,这意味着要创建一个带有 @Configuration 注解的类,
而在 XML 配置中,这意味着要创建一个 XML 文件,并且要以 beans 元素为根。
<?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">
</beans>
②、声明一个简单的 bean
<!--
<bean> 元素类似于 JavaConfig 中的 @Bean 注解
没有 id 的情况下,默认 ID 为 soundsystem.SgtPeppers#0,其中 #0 是一个计数的形式,用来区分相同类型的其他 bean。
注意:
①、在这里你不需要直接负责创建 SgtPeppers 的实例,而在 JavaConfig 配置时需要。
所以 XML 配置时,不能像 JavaConfig 那样可以通过任何可以想象的方法来创建 bean 实例。
②、在<bean>声明中,将 bean 的类型以字符串的形式设置在了 class 属性中。
所以 XML 配置时,不能保证 class 的值是真正的类。
-->
<bean id="compactDisc" class="soundsystem.SgtPeppers"/>
③、借助构造器注入初始化 bean
构造器注入的两种基本配置方案:
- constructor-arg 元素;
- 使用 Spring 3.0 所引入的 c-命名空间。
构造器注入 bean 引用(两种配置方案)
<!-- Spring 遇到这个<bean>元素时,它会创建一个 CDPlayer 实例 -->
<bean id="cdPlayer1" class="soundsystem.CDPlayer">
<!-- <constructor-arg> 元素会告诉 Spring 要将一个 ID 为 compactDisc 的 bean 引用传递到 CDPlayer 的构造器中 -->
<constructor-arg ref="compactDisc"/>
</bean>
<!--
该方法需要 XML 顶部声明其模式:xmlns:c="http://www.springframework.org/schema/c"
属性名以"c:"开头,也就是命名空间的前缀,接下来就是要装配的构造器参数名(即 CDPlayer.java中构造器参数名),在此之后是"-ref",这是一个命名的约定
它会告诉 Spring,正在装配的是一个 bean 的引用,这个 bean 的名字是 compactDisc,而不是字面量"compactDisc"。
-->
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:compactDisc-ref="compactDisc" />
显然,使用c-命名空间属性要简练的多。
Q:如何将字面量注入到构造器中
A:有时候需要用对象的引用装配对象,有时候需要用一个字面量值来配置对象。
package soundsystem;
/**
* 将已有的 SgtPeppers 替换为这个类。
*/
public class BlankDisc implements CompactDisc {
private String title;
private String artist;
public BlankDisc(String title, String artist) {
this.title = title;
this.artist = artist;
}
@Override
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}
<bean id="compactDisc1" class="soundsystem.BlankDisc">
<!-- 使用 value 属性,表明给定的值要以字面量的形式传入到构造器之中 -->
<constructor-arg value="title"/>
<constructor-arg value="artist"/>
</bean>
<bean id="compactDisc" class="soundsystem.BlankDisc"
c:title="title"
c:artist="artist"
/>
Q:如何装配集合
A:这种情况下,constructor-arg 能够实现,c-命名空间却无法做到。
package soundsystem;
import java.util.List;
/**
* 新添了一个集合类型的字段
*/
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 id="compactDisc1" class="soundsystem.BlankDisc">
<constructor-arg value="title"/>
<constructor-arg value="artist"/>
<constructor-arg>
<list>
<value>track01</value>
<value>track02</value>
<value>track03</value>
<value>track04</value>
<!-- 或者使用 <ref bean="beanName"> 实现对 bean 的引用 -->
</list>
</constructor-arg>
</bean>
我们也可以按照同样的方式来使用 Set 元素。
如果是 Set 的话,所有重复的值都会被忽略掉,存放顺序也不会得以保证。
④、设置属性
前面都是通过构造器注入的,没有使用属性的 Setter 方法。
Q:如何使用 Spring XML 实现属性注入。
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
public class CDPlayer {
private CompactDisc compactDisc;
@Autowired
public void setCompactDisc(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
public void play(){
compactDisc.play();
}
}
<bean id="cdPlayer1" class="soundsystem.CDPlayer">
<property name="compactDisc" ref="compactDisc"/>
</bean>
<!--
为了启用p-命名空间,需要在 XML 顶部声明其模式:xmlns:p="http://www.springframework.org/schema/p"
Spring 提供了更为简洁的 p-命名空间,作为<property>元素的替代方案
属性名以"p:"开头,接下来就是要注入的属性名,最后以"-ref"结尾,这会提示 Spring 要进行装配的是引用,而不是字面量。
-->
<bean id="cdPlayer" class="soundsystem.CDPlayer"
p:compactDisc-ref="compactDisc"/>
如何将字面量注入到属性中?
package 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;
}
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="titleValue"/>
<property name="artist" value="artistValue"/>
<property name="tracks">
<list>
<value>tracks01</value>
<value>tracks02</value>
<value>tracks03</value>
</list>
</property>
</bean>
Q:如何简化上述的 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: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">
<!-- 需要声明 util-命名空间 -->
<util:list id="trackList">
<value>tracks01</value>
<value>tracks02</value>
<value>tracks03</value>
</util:list>
<!-- 注意需要声明 p-命名空间 -->
<bean id="compactDisc" class="soundsystem.BlankDisc"
p:artist="artistValue"
p:title="titleValue"
p:tracks-ref="trackList"/>
</beans>
Spring util-命名空间中的元素
上一篇:Spring 如何通过 Java 代码装配 bean?
下一篇:自动装配、JavaConfig、XML 三种方案之间,怎么导入和混合配置?