2.4 通过XML装配bean

[复制链接]
发表于 2024-8-12 11:03:37 | 显示全部楼层 |阅读模式

到此为止,我们已经看到了如何让Spring自动发现和装配bean,还看到了如何进行手动干预,即通过JavaConfig显式地装配bean。但是,在装配bean的时候,还有一种可选方案,尽管这种方案可能不太合乎大家的心意,但是它在Spring中已经有很长的历史了。 在Spring刚刚出现的时候,XML是描述配置的主要方式。在Spring的名义下,我们创建了无数行XML代码。在一定程度上,Spring成为了XML配置的同义词。 尽管Spring长期以来确实与XML有着关联,但现在需要明确的是,XML不再是配置Spring的唯一可选方案。Spring现在有了强大的自动化配置和基于Java的配置,XML不应该再是你的第一选择了。 不过,鉴于已经存在那么多基于XML的Spring配置,所以理解如何在Spring中使用XML还是很重要的。但是,我希望本节的内容只是用来帮助你维护已有的XML配置,在完成新的Spring工作时,希望你会使用自动化配置和JavaConfig。 2.4.1 创建XML配置规范 在使用XML为Spring装配bean之前,你需要创建一个新的配置规范。在使用JavaConfig的时候,这意味着要创建一个带有@Configuration注解的类,而在XML配置中,这意味着要创建一个XML文件,并且要以<beans>元素为根。 最为简单的Spring 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/beans/spring-beans.xsd)
   [http://www.springframework.org/schema/context](http://www.springframework.org/schema/context)">
  <!-- configuration details go here -->
</beans>

很容易就能看出来,这个基本的XML配置已经比同等功能的JavaConfig类复杂得多了。作为起步,在JavaConfig中所需要的只是@Configuration,但在使用XML时,需要在配置文件的顶部声明多个XML模式(XSD)文件,这些文件定义了配置Spring的XML元素。借助Spring Tool Suite创建XML配置文件创建和管理Spring XML配置文件的一种简便方式是使用Spring Tool Suite(https://spring.io/tools/sts)。在Spring Tool Suite的菜单中,选择File>New>Spring Bean Configuration File,能够创建Spring XML配置文件,并且可以选择可用的配置命名空间。 用来装配bean的最基本的XML元素包含在spring-beans模式之中,在上面这个XML文件中,它被定义为根命名空间。<beans>是该模式中的一个元素,它是所有Spring配置文件的根元素。 在XML中配置Spring时,还有一些其他的模式。尽管在本书中,我更加关注自动化以及基于Java的配置,但是在本书讲解的过程中,当出现其他模式的时候,我至少会提醒你。 就这样,我们已经有了一个合法的Spring XML配置。不过,它也是一个没有任何用处的配置,因为它(还)没有声明任何bean。为了给予它生命力,让我们重新创建一下CD样例,只不过我们这次使用XML配置,而不是使用JavaConfig和自动化装配。 2.4.2 声明一个简单的<bean> 要在基于XML的Spring配置中声明一个bean,我们要使用spring-beans模式中的另外一个元素:<bean>。<bean>元素类似于JavaConfig中的@Bean注解。我们可以按照如下的方式声明CompactDiscbean:

<bean class="soundsystem.SgtPeppers" />

这里声明了一个很简单的bean,创建这个bean的类通过class属性来指定的,并且要使用全限定的类名。 因为没有明确给定ID,所以这个bean将会根据全限定类名来进行命名。在本例中,bean的ID将会是“soundsystem.SgtPeppers#0”。其中,“#0”是一个计数的形式,用来区分相同类型的其他bean。如果你声明了另外一个SgtPeppers,并且没有明确进行标识,那么它自动得到的ID将会是“soundsystem.SgtPeppers#1”。 尽管自动化的bean命名方式非常方便,但如果你要稍后引用它的话,那自动产生的名字就没有多大的用处了。因此,通常来讲更好的办法是借助id属性,为每个bean设置一个你自己选择的名字:

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

稍后将这个bean装配到CDPlayer bean之中的时候,你会用到这个具体的名字。减少繁琐为了减少XML中繁琐的配置,只对那些需要按名字引用的bean(比如,你需要将对它的引用注入到另外一个bean中)进行明确地命名。 在进一步学习之前,让我们花点时间看一下这个简单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配置的合法性。 以上介绍的只是JavaConfig要优于XML配置的部分原因。我建议在为你的应用选择配置风格时,要记住XML配置的这些缺点。接下来,我们继续Spring XML配置的学习进程,了解如何将SgtPeppersbean注入到CDPlayer之中。 2.4.3 借助构造器注入初始化bean 在Spring XML配置中,只有一种声明bean的方式:使用<bean>元素并指定class属性。Spring会从这里获取必要的信息来创建bean。 但是,在XML中声明DI时,会有多种可选的配置方案和风格。具体到构造器注入,有两种基本的配置方案可供选择: ·<constructor-arg>元素 ·使用Spring 3.0所引入的c-命名空间 两者的区别在很大程度就是是否冗长烦琐。可以看到,<constructor-arg>元素比使用c-命名空间会更加冗长,从而导致XML更加难以读懂。另外,有些事情<constructor-arg>可以做到,但是使用c-命名空间却无法实现。 在介绍Spring XML的构造器注入时,我们将会分别介绍这两种可选方案。首先,看一下它们各自如何注入bean引用。 构造器注入bean引用 按照现在的定义,CDPlayerbean有一个接受CompactDisc类型的构造器。这样,我们就有了一个很好的场景来学习如何注入bean的引用。 现在已经声明了SgtPeppers bean,并且SgtPeppers类实现了CompactDisc接口,所以实际上我们已经有了一个可以注入到CDPlayerbean中的bean。我们所需要做的就是在XML中声明CDPlayer并通过ID引用SgtPeppers:

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

当Spring遇到这个<bean>元素时,它会创建一个CDPlayer实例。<constructor-arg>元素会告知Spring要将一个ID为compactDisc的bean引用传递到CDPlayer的构造器中。 作为替代的方案,你也可以使用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://www.springframework.org/schema/c"
  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/beans/spring-beans.xsd)">
...
</beans>

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

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

在这里,我们使用了c-命名空间来声明构造器参数,它作为<bean>元素的一个属性,不过这个属性的名字有点诡异。图2.1描述了这个属性名是如何组合而成的。

image.png 属性名以“c:”开头,也就是命名空间的前缀。接下来就是要装配的构造器参数名,在此之后是“-ref”,这是一个命名的约定,它会告诉Spring,正在装配的是一个bean的引用,这个bean的名字是compactDisc,而不是字面量“compactDisc”。 很显然,使用c-命名空间属性要比使用<constructor-arg>元素简练得多。这是我很喜欢它的原因之一。除了更易读之外,当我在编写样例代码时,c-命名空间属性能够更加有助于使代码的长度保持在书的边框之内。 在编写前面的样例时,关于c-命名空间,有一件让我感到困扰的事情就是它直接引用了构造器参数的名称。引用参数的名称看起来有些怪异,因为这需要在编译代码的时候,将调试标志(debug symbol)保存在类代码中。如果你优化构建过程,将调试标志移除掉,那么这种方式可能就无法正常执行了。 替代的方案是我们使用参数在整个参数列表中的位置信息:

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

这个c-命名空间属性看起来似乎比上一种方法更加怪异。我将参数的名称替换成了“0”,也就是参数的索引。因为在XML中不允许数字作为属性的第一个字符,因此必须要添加一个下画线作为前缀。 使用索引来识别构造器参数感觉比使用名字更好一些。即便在构建的时候移除掉了调试标志,参数却会依然保持相同的顺序。如果有多个构造器参数的话,这当然是很有用处的。在这里因为只有一个构造器参数,所以我们还有另外一个方案——根本不用去标示参数:

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

到目前为止,这是最为奇特的一个c-命名空间属性,这里没有参数索引或参数名。只有一个下画线,然后就是用“-ref”来表明正在装配的是一个引用。 我们已经将引用装配到了其他的bean之中,接下来看一下如何将字面量值(literal value)装配到构造器之中。 将字面量注入到构造器中 迄今为止,我们所做的DI通常指的都是类型的装配——也就是将对象的引用装配到依赖于它们的其他对象之中——而有时候,我们需要做的只是用一个字面量值来配置对象。为了阐述这一点,假设你要创建CompactDisc的一个新实现,如下所示:

package soundsystem;
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);
  }
}

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

<bean id="compactDisc"
    class="soundsystem.BlankDisc">
  <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
  <constructor-arg value="The Beatles" />
</bean>

我们再次使用<constructor-arg>元素进行构造器参数的注入。但是这一次我们没有使用“ref”属性来引用其他的bean,而是使用了value属性,通过该属性表明给定的值要以字面量的形式注入到构造器之中。 如果要使用c-命名空间的话,这个例子又该是什么样子呢?第一种方案是引用构造器参数的名字:

<bean id="compactDisc"
    class="soundsystem.BlankDisc"
    c:_title="Sgt. Pepper's Lonely Hearts Club Band"
    c:_artist="The Beatles" />

可以看到,装配字面量与装配引用的区别在于属性名中去掉了“-ref”后缀。与之类似,我们也可以通过参数索引装配相同的字面量值,如下所示:

<bean id="compactDisc"
    class="soundsystem.BlankDisc"
    c:_0="Sgt. Pepper's Lonely Hearts Club Band"
    c:_1="The Beatles" />

XML不允许某个元素的多个属性具有相同的名字。因此,如果有两个或更多的构造器参数的话,我们不能简单地使用下画线进行标示。但是如果只有一个构造器参数的话,我们就可以这样做了。为了完整地展现该功能,假设BlankDisc只有一个构造器参数,这个参数接受唱片的名称。在这种情况下,我们可以在Spring中这样声明它:

<bean id="compactDisc" class="soundsystem.BlankDisc"
    c:_="Sgt. Pepper's Lonely Hearts Club Band" />

在装配bean引用和字面量值方面,<constructor-arg>和c-命名空间的功能是相同的。但是有一种情况是<constructor-arg>能够实现,c-命名空间却无法做到的。接下来,让我们看一下如何将集合装配到构造器参数中。 装配集合 到现在为止,我们假设CompactDisc在定义时只包含了唱片名称和艺术家的名字。如果现实世界中的CD也是这样的话,那么在技术上就不会任何的进展。CD之所以值得购买是因为它上面所承载的音乐。大多数的CD都会包含十多个磁道,每个磁道上包含一首歌。 如果使用CompactDisc为真正的CD建模,那么它也应该有磁道列表的概念。请考虑下面这个新的BlankDisc:

package soundsystem.collections;
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);
   }
  }
}

这个变更会对Spring如何配置bean产生影响,在声明bean的时候,我们必须要提供一个磁道列表。 最简单的办法是将列表设置为null。因为它是一个构造器参数,所以必须要声明它,不过你可以采用如下的方式传递null给它:

<bean id="compactDisc" class="soundsystem.BlankDisc">
  <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
  <constructor-arg value="The Beatles" />
  <constructor-arg><null/></constructor-arg>
</bean>

<null/>元素所做的事情与你的期望是一样的:将null传递给构造器。这并不是解决问题的好办法,但在注入期它能正常执行。当调用play()方法时,你会遇到NullPointerException异常,因此这并不是理想的方案。 更好的解决方法是提供一个磁道名称的列表。要达到这一点,我们可以有多个可选方案。首先,可以使用<list>元素将其声明为一个列表:

<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>Getting Better</value>
    <value>Fixing a Hole</value>
    <!-- ...other tracks omitted for brevity... -->
   </list>
  </constructor-arg>
</bean>

其中,<list>元素是<constructor-arg>的子元素,这表明一个包含值的列表将会传递到构造器中。其中,<value>元素用来指定列表中的每个元素。 与之类似,我们也可以使用<ref>元素替代<value>,实现bean引用列表的装配。例如,假设你有一个Discography类,它的构造器如下所示:

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

那么,你可以采取如下的方式配置Discography bean:

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

当构造器参数的类型是java.util.List时,使用<list>元素是合情合理的。尽管如此,我们也可以按照同样的方式使用<set>元素:

<bean id="compactDisc" class="soundsystem.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>

<set>和<list>元素的区别不大,其中最重要的不同在于当Spring创建要装配的集合时,所创建的是java.util.Set还是java.util.List。如果是Set的话,所有重复的值都会被忽略掉,存放顺序也不会得以保证。不过无论在哪种情况下,<set>或<list>都可以用来装配List、Set甚至数组。 在装配集合方面,<constructor-arg>比c-命名空间的属性更有优势。目前,使用c-命名空间的属性无法实现装配集合的功能。 使用<constructor-arg>和c-命名空间实现构造器注入时,它们之间还有一些细微的差别。但是到目前为止,我们所涵盖的内容已经足够了,尤其是像我之前所建议的那样,要首选基于Java的配置而不是XML。因此,与其不厌其烦地花费时间讲述如何使用XML进行构造器注入,还不如看一下如何使用XML来装配属性。 2.4.4 设置属性 到目前为止,CDPlayer和BlankDisc类完全是通过构造器注入的,没有使用属性的Setter方法。接下来,我们就看一下如何使用Spring XML实现属性注入。假设属性注入的CDPlayer如下所示:

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

该选择构造器注入还是属性注入呢?作为一个通用的规则,我倾向于对强依赖使用构造器注入,而对可选性的依赖使用属性注入。按照这个规则,我们可以说对于BlankDisc来讲,唱片名称、艺术家以及磁道列表是强依赖,因此构造器注入是正确的方案。不过,对于CDPlayer来讲,它对CompactDisc是强依赖还是可选性依赖可能会有些争议。虽然我不太认同,但你可能会觉得即便没有将CompactDisc装入进去,CDPlayer依然还能具备一些有限的功能。 现在,CDPlayer没有任何的构造器(除了隐含的默认构造器),它也没有任何的强依赖。因此,你可以采用如下的方式将其声明为Spring bean:

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

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

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

<property>元素为属性的Setter方法所提供的功能与<constructor-arg>元素为构造器所提供的功能是一样的。在本例中,它引用了ID为compactDisc的bean(通过ref属性),并将其注入到compactDisc属性中(通过setCompactDisc()方法)。如果你现在运行测试的话,它应该就能通过了。 我们已经知道,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
   [http://www.springframework.org/schema/beans/spring-beans.xsd](http://www.springframework.org/schema/beans/spring-beans.xsd)">
  ...
</bean>

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

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

image.png

图2.2 借助Spring的p-命名空间,将bean引用注入到属性中 首先,属性的名字使用了“p:”前缀,表明我们所设置的是一个属性。接下来就是要注入的属性名。最后,属性的名称以“-ref”结尾,这会提示Spring要进行装配的是引用,而不是字面量。 将字面量注入到属性中 属性也可以注入字面量,这与构造器参数非常类似。作为示例,我们重新看一下BlankDisc bean。不过,BlankDisc这次完全通过属性注入进行配置,而不是构造器注入。新的BlankDisc类如下所示:

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

现在,它不再强制要求我们装配任何的属性。你可以按照如下的方式创建一个BlankDiscbean,它的所有属性全都是空的:

<bean id="reallyBlankDisc"
    class="soundsystem.BlankDisc" />

当然,如果在装配bean的时候不设置这些属性,那么在运行期CD播放器将不能正常播放内容。play()方法可能会遇到的输出内容是“Playing null by null”,随之会抛出NullPointerException异常,这是因为我们没有指定任何的磁道。所以,我们需要装配这些属性,可以借助<property>元素的value属性实现该功能:

<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>
    <!-- ...other tracks omitted for brevity... -->
   </list>
  </property>
</bean>

在这里,除了使用<property>元素的value属性来设置title和artist,我们还使用了内嵌的<list>元素来设置tracks属性,这与之前通过<constructor-arg>装配tracks是完全一样的。 另外一种可选方案就是使用p-命名空间的属性来完成该功能:

<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>
    <!-- ...other tracks omitted for brevity... -->
   </list>
  </property>
</bean>

与c-命名空间一样,装配bean引用与装配字面量的唯一区别在于是否带有“-ref”后缀。如果没有“-ref”后缀的话,所装配的就是字面量。 但需要注意的是,我们不能使用p-命名空间来装配集合,没有便利的方式使用p-命名空间来指定一个值(或bean引用)的列表。但是,我们可以使用Spring util-命名空间中的一些功能来简化BlankDiscbean。 首先,需要在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/beans/spring-beans.xsd)
   [http://www.springframework.org/schema/util](http://www.springframework.org/schema/util)
   [http://www.springframework.org/schema/util/spring-util.xsd](http://www.springframework.org/schema/util/spring-util.xsd)">
   ...
</beans>

util-命名空间所提供的功能之一就是util:list元素,它会创建一个列表的bean。借助util:list,我们可以将磁道列表转移到BlankDisc bean之外,并将其声明到单独的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>
  <!-- ...other tracks omitted for brevity... -->
</util:list>

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

<bean id="compactDisc"
    class="soundsystem.BlankDisc"
    p:title="Sgt. Pepper's Lonely Hearts Club Band"
    p:artist="The Beatles"
    p:tracks-ref="trackList" />

util:list只是util-命名空间中的多个元素之一。表2.1列出了util-命名空间提供的所有元素。 在需要的时候,你可能会用到util-命名空间中的部分成员。但现在,在结束本章前,我们看一下如何将自动化配置、JavaConfig以及XML配置混合并匹配在一起。 表2.1 Spring util-命名空间中的元素

image.png

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

GMT+8, 2025-6-6 23:31 , Processed in 0.070505 second(s), 34 queries Archiver|手机版|小黑屋|Attic ( 京ICP备2020048627号 )

快速回复 返回顶部 返回列表