丰富Bean的配置

关于Bean是如何配置的,大家并不陌生。毕竟前文曾有涉及,虽然比较粗浅。却也介绍了如何写份XML配置文件,告诉Spring容器怎样创建Bean,怎样注入依赖,等等。其中要点如下:
1.<bean>元素用于配置Bean;具有id,class两个重要XML属性:id用于指定Bean的唯一标识符;class用于指定Bean的类型,其值为全限定类名。
2.<property>元素用于配置通过属性注入依赖;具有name,value,ref三个重要XML属性:name用于指定Bean的属性名;value用于指定注入的字面量值;ref用于指定注入的Bean引用。

因此,假如com.dream包现有这样一些类:

 1 public class Music {
 2     private String musicName = null;
 3 
 4     public String getMusicName() {
 5         return this.musicName;
 6     }
 7 
 8     public void setMusicName(String musicName) {
 9         this.musicName = musicName;
10     }
11 }
 1 public class Player {
 2     private Music playingMusic = null;
 3 
 4     public Music getPlayingMusic() {
 5         return this.playingMusic;
 6     }
 7 
 8     public void setPlayingMusic(Music playingMusic) {
 9         this.playingMusic = playingMusic;
10     }
11 }

则可这样配置Bean:

1 <beans /* 省略命名空间和XSD模式文件声明 */>
2     <bean id="music" class="com.dream.Music">
3         <property name="musicName" value="执着"/>
4     </bean>
5     <bean id="player" class="com.dream.Player">
6         <property name="playingMusic" ref="music"/>
7     </bean>
8 </beans>

这段配置能够告诉Spring容器创建music,player这两个Bean之后,通过属性注入Bean所需的依赖。也就是通过<property>元素,把“执着”注入music的musicName属性,把music注入player的playingMusic属性。这些配置大家都很熟悉,无需多叙。可是我们尚不知道的是,我们还能使用p-命名空间代替<property>元素描述依赖的注入。而这,需要修改XML配置文件如下:

1 <beans xmlns:p="http://www.springframework.org/schema/p"
2        /* 省略命名空间和XSD模式文件声明 */>
3     <bean id="music" class="com.dream.Music" p:musicName="执着"/>
4     <bean id="player" class="com.dream.Player" p:playingMusic-ref="music"/>
5 </beans>

新的配置引入p-命名空间 xmlns:p="http://www.springframework.org/schema/p" 之后,做了两处改动:
1.使用 p:musicName="执着" 代替<property>元素注入“执着”这个字面量值。
2.使用 p:playingMusic-ref="music" 代替<property>元素注入music这个Bean引用。

这是怎么回事呢?

原来,p-命名空间可以代替<property>元素,以XML属性这种简洁紧凑的方式描述通过属性注入依赖。因此,字面量值注入能用p-命名空间这样描述: p:Bean的属性名=“字面量值” 。也就是以 p: 作为开头,随后带上Bean的属性名,带上等号,带上字面量值就行;Bean引用注入能用p-命名空间这样描述: p:Bean的属性名-ref=“即将注入的Bean的ID” 。也就是以 p: 作为开头,随后带上Bean的属性名,带上 -ref 后缀,带上等号,带上即将注入的Bean的ID即可。

因此,修改之后的配置使用p-命名空间 p:musicName="执着" 代替 <property name="musicName" value="执着"/> 描述“执着”这个字面量值的注入;使用p-命名空间 p:playingMusic-ref="music" 代替 <property name="playingMusic" ref="music"/> 描述music这个Bean引用的注入。

于是我们知道了,p-命名空间能以一种简洁紧凑的方式代替<property>元素描述依赖的注入。至于p-命名空间和<property>元素哪种较好,并无定论,可依个人偏好而定。可是一旦选好了,最好保持整个项目的统一;不要这里使用<property>元素,那里使用p-命名空间。

构造函数注入

很多时候,我们希望一步到位,通过构造函数完成Bean的创建与装配。为了满足这样的需求,Spring提供了些支持,让我们能向XML配置文件提供一些信息,告诉Spring容器创建Bean的时候不是调用默认构造函数,而是调用其它具有某些参数的构造函数;从而能在创建Bean的同时通过构造函数注入Bean所需的依赖,完成Bean的创建与装配。

因此,假如com.dream包现有这样一些类:

1 public class Music {
2     private String musicName = null;
3 
4     public Music(String musicName) {
5         this.musicName = musicName;
6     }
7 }
1 public class Player {
2     private Music playingMusic = null;
3 
4     public Player(Music playingMusic) {
5         this.playingMusic = playingMusic;
6     }
7 }

则可这样配置Bean:

1 <beans /* 省略命名空间和XSD模式文件声明 */>
2     <bean id="music" class="com.dream.Music">
3         <constructor-arg type="java.lang.String" value="执着"/>
4     </bean>
5     <bean id="player" class="com.dream.Player">
6         <constructor-arg type="com.dream.Music" ref="music"/>
7     </bean>
8 </beans>

可以看到构造函数注入是用<constructor-arg>元素配置的;具有type,value,ref三个重要XML属性。type用于指定构造函数的参数类型,其值为全限定类名;value用于指定注入的字面量值;ref用于指定注入的Bean引用。Spring容器调用类的构造函数创建Bean之前会先查看XML配置信息,看看即将调用的构造函数具有多少参数,每个参数是什么类型的,值是多少;之后,Spring容器根据配置文件提供的信息调用符合条件的构造函数完成Bean的创建与装配。

就该示例而言,Spring容器读取配置信息之后,发现music这个Bean的创建需要调用的构造函数具有一个String类型的参数。于是,Spring容器根据配置文件提供的信息把字符串“执着”传给符合条件的构造函数,并在调用之后完成Bean的创建与装配;发现player这个Bean的创建需要调用的构造函数具有一个Music类型的参数。于是,Spring容器根据配置文件提供的信息把music这个Bean传给符合条件的构造函数,并在调用之后完成Bean的创建与装配。

讲到这里,兴许大家开始困惑了:“如果配置的构造函数具有多个相同类型的参数,Spring容器调用构造函数的时候,怎么知道该把哪个值传给哪个参数,完成Bean的创建与装配呢?”

关于这个问题,我们可以引入<constructor-arg>元素的index属性进行解决。index属性能够指定构造函数的参数索引,表明配置的是构造函数的第几个参数。其中,第一个参数的值是0,第二个参数的值是1,第三个参数的值是2,以此类推。Spring容器创建Bean的时候,会按参数索引的顺序依次把相应的参数值传给构造函数进行Bean的创建。自然而然的,关于因为相同类型的参数多于一个而无法正确注入依赖的问题也就迎刃而解了。

另外,除了参数索引,我们也能使用<constructor-arg>元素的name属性解决这个问题。name属性用于指定构造函数的参数名,表明参数值应该传给参数名为某值的参数。而构造函数的参数名一定是各不相同的,因此能够解决这个问题。只是name属性的使用有个限制,需要我们打开调试标记(Debug Flag)编译代码才行。否则,Spring容器无法得知构造函数的参数名,也就无法通过参数名传递参数值调用构造函数了。

还有,同p-命名空间能够代替<property>元素一样,Spring也提供了c-命名空间用于代替<constructor-arg>元素。而这,可以修改XML配置文件如下:

1 <beans xmlns:c="http://www.springframework.org/schema/c"
2        /* 省略命名空间和XSD模式文件声明 */>
3     <bean id="music" class="com.dream.Music" c:musicName="执着"/>
4     <bean id="player" class="com.dream.Player" c:playingMusic-ref="music"/>
5 </beans>

新的配置引入c-命名空间 xmlns:c="http://www.springframework.org/schema/c" 之后,做了两处改动:
1.使用 c:musicName="执着" 代替<constructor-arg>元素注入“执着”这个字面量值。
2.使用 c:playingMusic-ref="music" 代替<constructor-arg>元素注入music这个Bean引用。

这是怎么回事呢?

原来,c-命名空间可以代替<constructor-arg>元素,以XML属性这种简洁紧凑的方式描述通过构造函数注入依赖。因此,字面量值注入能用c-命名空间这样描述: c:构造函数的参数名=“字面量值” 。也就是以 c: 作为开头,随后带上构造函数的参数名,带上等号,带上字面量值就行;Bean引用注入能用c-命名空间这样描述: c:构造函数的参数名-ref=“即将注入的Bean的ID” 。也就是以 c: 作为开头,随后带上构造函数的参数名,带上 -ref 后缀,带上等号,带上即将注入的Bean的ID即可。

因此,修改之后的配置使用c-命名空间 c:musicName="执着" 代替 <constructor-arg type="java.lang.String" value="执着"/> 描述“执着”这个字面量值的注入;使用c-命名空间 c:playingMusic-ref="music" 代替 <constructor-arg type="com.dream.Music" ref="music"/> 描述music这个Bean引用的注入。

读到这里,兴许大家已经察觉:“c-命名空间用到了参数名,而Spring容器获取参数名需要调试标志。如果编译代码的时候没有启用调试标志,这种配置方式岂不是有问题?”

是的,确实如此。因此,c-命名空间也支持参数索引。如下所示:

1 <beans xmlns:c="http://www.springframework.org/schema/c"
2        /* 省略命名空间和XSD模式文件声明 */>
3     <bean id="music" class="com.dream.Music" c:_0="执着"/>
4     <bean id="player" class="com.dream.Player" c:_0-ref="music"/>
5 </beans>

引入参数索引之后,原来的 c:musicName="执着" 变成 c:_0="执着" ,原来的 c:playingMusic-ref="music" 变成 c:_0-ref="music" 。也就是说,原来的参数名变成下划线+索引。其中,索引前面的下划线是必须的,因为XML不允许属性名以数字作为开头。引入参数索引之后,Spring容器创建Bean的时候,会按参数索引指定的顺序依次把相应的参数值传给构造函数,并在调用之后完成Bean的创建与装配。

于是我们知道了,Spring容器既能通过属性注入依赖,也能通过构造函数注入依赖。至于该用属性注入还是构建函数注入,则是个人偏好问题。一般而言,强依赖(也就是只有完成注入,程序才能正常运行的依赖)通常选用构造函数注入,可选依赖(也就是不管注入有没有完成,程序都能正常运行的依赖)通常选用属性注入。

静态工厂方法注入

总有那么一些时候,我们的类存在一些专门用于创建对象的静态方法,俗称静态工厂方法。如果我们希望通过静态工厂方法创建Bean,只需向配置文件提供一些信息,告诉Spring容器调用静态工厂方法完成Bean的创建与装配即可。

因此,假如com.dream包现有这样一些类:

 1 public class Music {
 2     private String musicName = null;
 3 
 4     public Music(String musicName) {
 5         this.musicName = musicName;
 6     }
 7 
 8     public static Music staticFactory(String musicName) {
 9         return new Music(musicName);
10     }
11 }
 1 public class Player {
 2     private Music playingMusic = null;
 3 
 4     public Player(Music playingMusic) {
 5         this.playingMusic = playingMusic;
 6     }
 7 
 8     public static Player staticFactory(Music playingMusic) {
 9         return new Player(playingMusic);
10     }
11 }

则可这样配置Bean:

1 <beans /* 省略命名空间和XSD模式文件声明 */>
2     <bean id="music" class="com.dream.Music" factory-method="staticFactory">
3         <constructor-arg type="java.lang.String" value="执着"/>
4     </bean>
5     <bean id="player" class="com.dream.Player" factory-method="staticFactory">
6         <constructor-arg type="com.dream.Music" ref="music"/>
7     </bean>
8 </beans>

可以看到<bean>元素新添了个factory-method属性,用于指定类的静态工厂方法;而静态工厂方法所属的类由class属性指定,所需的参数由<constructor-arg>元素指定。当然,如果静态工厂方法创建的Bean存在属性,也可通过<property>元素指定依赖注入。

因此,这段配置用于告诉Spring容器:music这个Bean需要调用com.dream.Music类的staticFactory静态工厂方法进行创建,而且调用的时候需要注入“执着”这个字面量值;player这个Bean需要调用com.dream.Player类的staticFactory静态工厂方法进行创建,而且调用的时候需要注入music这个Bean引用。

实例工厂方法注入

工厂方法除了静态工厂方法,还有实例工厂方法。如果我们希望通过实例工厂方法创建Bean,只需向配置文件提供一些信息,告诉Spring容器调用某个Bean的实例工厂方法完成Bean的创建与装配即可。

因此,假如com.dream包现有这样一些类:

 1 public class Music {
 2     private String musicName = null;
 3 
 4     public Music() {
 5     }
 6 
 7     public Music(String musicName) {
 8         this.musicName = musicName;
 9     }
10 
11     public Music instanceFactory(String musicName) {
12         return new Music(musicName);
13     }
14 }
 1 public class Player {
 2     private Music playingMusic = null;
 3 
 4     public Player() {
 5     }
 6 
 7     public Player(Music playingMusic) {
 8         this.playingMusic = playingMusic;
 9     }
10 
11     public Player instanceFactory(Music playingMusic) {
12         return new Player(playingMusic);
13     }
14 }

则可这样配置Bean:

 1 <beans /* 省略命名空间和XSD模式文件声明 */>
 2     <bean id="music_1" class="com.dream.Music"/>
 3     <bean id="music_2" factory-bean="music_1" factory-method="instanceFactory">
 4         <constructor-arg type="java.lang.String" value="执着"/>
 5     </bean>
 6 
 7     <bean id="player_1" class="com.dream.Player"/>
 8     <bean id="player_2" factory-bean="player_1" factory-method="instanceFactory">
 9         <constructor-arg type="com.dream.Music" ref="music_2"/>
10     </bean>
11 </beans>

这里配置了四个Bean:music_1,music_2,player_1,player_2。其中,music_2,player_2就是通过实例工厂方法创建的。

配置实例工厂方法时,需用factory-method属性指定实例工厂方法,factory-bean属性指定实例工厂方法所属的Bean,<constructor-arg>元素指定实例工厂方法所需的参数。当然,如果实例工厂方法创建的Bean存在属性,也可通过<property>元素指定依赖注入。

因此,这段配置用于告诉Spring容器:music_2这个Bean需要调用music_1这个Bean的instanceFactory实例工厂方法进行创建,而且调用的时候需要注入“执着”这个字面量值;player_2这个Bean需要调用player_1这个Bean的instanceFactory实例工厂方法进行创建,而且调用的时候需要注入music_2这个Bean引用。

NULL值注入

NULL值的注入可用<null>元素进行描述,如下所示:

1 <bean id="player_1" class="com.dream.Player">
2     <constructor-arg type="com.dream.Music">
3         <null />
4     </constructor-arg>
5 </bean>
1 <bean id="player_2" class="com.dream.Player">
2     <property name="playingMusic">
3         <null />
4     </property>
5 </bean>

集合注入

Java提供了多种类型的集合,常见的有List,Set,Map,等等。自然而然的,Spring提供了些支持,用于配置集合的注入。

因此,假如com.dream包现有这样一些类:

 1 public class Music {
 2     private List<String> musicNameList = null;
 3 
 4     public List<String> getMusicNameList() {
 5         return this.musicNameList;
 6     }
 7 
 8     public void setMusicNameList(List<String> musicNameList) {
 9         this.musicNameList = musicNameList;
10     }
11 }
 1 public class Player {
 2     private List<Music> playingMusicList = null;
 3 
 4     public List<Music> getPlayingMusicList() {
 5         return this.playingMusicList;
 6     }
 7 
 8     public void setPlayingMusicList(List<Music> playingMusicList) {
 9         this.playingMusicList = playingMusicList;
10     }
11 }

则可这样配置Bean:

 1 <beans /* 省略命名空间和XSD模式文件声明 */>
 2     <bean id="music_1" class="com.dream.Music"/>
 3     <bean id="music_2" class="com.dream.Music">
 4         <property name="musicNameList">
 5             <list>
 6                 <value>执着</value>
 7                 <value>一生有你</value>
 8             </list>
 9         </property>
10     </bean>
11     <bean id="player" class="com.dream.Player">
12         <property name="playingMusicList">
13             <list>
14                 <ref bean="music_1"/>
15                 <ref bean="music_2"/>
16             </list>
17         </property>
18     </bean>
19 </beans>

可以看到List类型的集合能用<list>元素配置。底下有个<value>元素,用于配置字面量值集合;有个<ref>元素,用于配置Bean引用集合。这些大家一看便知,不必详述。重点在于,Spring是否也提供了诸如p-命名空间,c-命名空间之类的替代方案,用于简化集合的配置呢?

当然有的。要知道p-命名空间,c-命名空间是不支持集合的。因此,Spring在spring-util.xsd模式文件里定义了些XML元素,用于描述诸如集合之类的创建信息。而这,需要引入spring-util.xsd模式文件之后修改如下:

 1 <beans /* 省略命名空间和XSD模式文件声明 */
 2        xmlns:util="http://www.springframework.org/schema/util"
 3        xsi:schemaLocation="
 4        /* 省略命名空间和XSD模式文件声明 */
 5        http://www.springframework.org/schema/util
 6        http://www.springframework.org/schema/util/spring-util.xsd">
 7 
 8     <bean id="music_1" class="com.dream.Music" />
 9     <bean id="music_2" class="com.dream.Music">
10         <property name="musicNameList" ref="utilMusicNameList"/>
11     </bean>
12     <bean id="player" class="com.dream.Player">
13         <property name="playingMusicList" ref="utilPlayingMusicList" />
14     </bean>
15 
16     <util:list id="utilMusicNameList">
17         <value>执着</value>
18         <value>一生有你</value>
19     </util:list>
20     <util:list id="utilPlayingMusicList">
21         <ref bean="music_1" />
22         <ref bean="music_2" />
23     </util:list>
24 
25 </beans>

可以看到spring-util.xsd模式文件定义了<util:list>元素,用于配置如何创建List类型的集合。底下有个<value>元素,用于配置字面量值集合;有个<ref>元素,用于配置Bean引用集合。因此,这段配置创建了两个List类型的集合:一个集合的id是utilMusicNameList;一个集合的id是utilPlayingMusicList。之后,把集合utilMusicNameList注入music_2的musicNameList属性,把集合utilPlayingMusicList注入player的playingMusicList属性,完成集合的注入。

假如com.dream包现有这样一些类:

 1 public class Music {
 2     private Set<String> musicNameSet = null;
 3 
 4     public Set<String> getMusicNameSet() {
 5         return this.musicNameSet;
 6     }
 7 
 8     public void setMusicNameSet(Set<String> musicNameSet) {
 9         this.musicNameSet = musicNameSet;
10     }
11 }
 1 public class Player {
 2     private Set<Music> playingMusicSet = null;
 3 
 4     public Set<Music> getPlayingMusicSet() {
 5         return this.playingMusicSet;
 6     }
 7 
 8     public void setPlayingMusicSet(Set<Music> playingMusicSet) {
 9         this.playingMusicSet = playingMusicSet;
10     }
11 }

则可这样配置Bean:

 1 <beans /* 省略命名空间和XSD模式文件声明 */>
 2     <bean id="music_1" class="com.dream.Music" />
 3     <bean id="music_2" class="com.dream.Music">
 4         <property name="musicNameSet">
 5             <set>
 6                 <value>执着</value>
 7                 <value>一生有你</value>
 8             </set>
 9         </property>
10     </bean>
11     <bean id="player" class="com.dream.Player">
12         <property name="playingMusicSet">
13             <set>
14                 <ref bean="music_1" />
15                 <ref bean="music_2" />
16             </set>
17         </property>
18     </bean>
19 </beans>

可以看到Set类型的集合能用<set>元素配置。底下有个<value>元素,用于配置字面量值集合;有个<ref>元素,用于配置Bean引用集合。这些大家一看便知,不必详述。重点在于,Set类型的集合同样也能使用util元素进行配置。如下所示:

 1 <beans /* 省略命名空间和XSD模式文件声明 */
 2        xmlns:util="http://www.springframework.org/schema/util"
 3        xsi:schemaLocation="
 4        /* 省略命名空间和XSD模式文件声明 */
 5        http://www.springframework.org/schema/util
 6        http://www.springframework.org/schema/util/spring-util.xsd">
 7 
 8     <bean id="music_1" class="com.dream.Music" />
 9     <bean id="music_2" class="com.dream.Music">
10         <property name="musicNameSet" ref="utilMusicNameSet"/>
11     </bean>
12     <bean id="player" class="com.dream.Player">
13         <property name="playingMusicSet" ref="utilPlayingMusicSet" />
14     </bean>
15 
16     <util:set id="utilMusicNameSet">
17         <value>执着</value>
18         <value>一生有你</value>
19     </util:set>
20     <util:set id="utilPlayingMusicSet">
21         <ref bean="music_1" />
22         <ref bean="music_2" />
23     </util:set>
24 
25 </beans>

可以看到spring-util.xsd模式文件定义了<util:set>元素,用于配置如何创建Set类型的集合。底下有个<value>元素,用于配置字面量值集合;有个<ref>元素,用于配置Bean引用集合。因此,这段配置创建了两个Set类型的集合:一个集合的id是utilMusicNameSet;一个集合的id是utilPlayingMusicSet。之后,把集合utilMusicNameSet注入music_2的musicNameSet属性,把集合utilPlayingMusicSet注入player的playingMusicSet属性,完成集合的注入。

假如com.dream包现有这样一些类:

 1 public class Music {
 2     private Map<String, String> musicNameMap = null;
 3 
 4     public Map<String, String> getMusicNameMap() {
 5         return this.musicNameMap;
 6     }
 7 
 8     public void setMusicNameMap(Map<String, String> musicNameMap) {
 9         this.musicNameMap = musicNameMap;
10     }
11 }
 1 public class Player {
 2     private Map<Music, Music> playingMusicMap = null;
 3 
 4     public Map<Music, Music> getPlayingMusicMap() {
 5         return this.playingMusicMap;
 6     }
 7 
 8     public void setPlayingMusicMap(Map<Music, Music> playingMusicMap) {
 9         this.playingMusicMap = playingMusicMap;
10     }
11 }

则可这样配置Bean:

 1 <beans /* 省略命名空间和XSD模式文件声明 */>
 2     <bean id="music_1" class="com.dream.Music" />
 3     <bean id="music_2" class="com.dream.Music">
 4         <property name="musicNameMap">
 5             <map>
 6                 <entry key="执着" value="执着" />
 7                 <entry key="一生有你" value="一生有你" />
 8             </map>
 9         </property>
10     </bean>
11     <bean id="player" class="com.dream.Player">
12         <property name="playingMusicMap">
13             <map>
14                 <entry key-ref="music_1" value-ref="music_1" />
15                 <entry key-ref="music_2" value-ref="music_2" />
16             </map>
17         </property>
18     </bean>
19 </beans>

可以看到Map类型的集合能用<map>元素和<entry>元素配置。<entry>元素有个key属性,用于配置字面量值的字典键;有个key-ref属性,用于配置Bean引用的字典键;有个value属性,用于配置字面量值的字典值;有个value-ref属性,用于配置Bean引用的字典值。这些大家一看便知,不必详述。重点在于,Map类型的集合同样也能使用util元素进行配置。如下所示:

 1 <beans /* 省略命名空间和XSD模式文件声明 */
 2        xmlns:util="http://www.springframework.org/schema/util"
 3        xsi:schemaLocation="
 4        /* 省略命名空间和XSD模式文件声明 */
 5        http://www.springframework.org/schema/util
 6        http://www.springframework.org/schema/util/spring-util.xsd">
 7 
 8     <bean id="music_1" class="com.dream.Music" />
 9     <bean id="music_2" class="com.dream.Music">
10         <property name="musicNameMap" ref="utilMusicNameMap"/>
11     </bean>
12     <bean id="player_1" class="com.dream.Player">
13         <property name="playingMusicMap" ref="utilPlayingMusicMap" />
14     </bean>
15 
16     <util:map id="utilMusicNameMap">
17         <entry key="执着" value="执着" />
18         <entry key="一生有你" value="一生有你" />
19     </util:map>
20     <util:map id="utilPlayingMusicMap">
21         <entry key-ref="music_1" value-ref="music_1" />
22         <entry key-ref="music_2" value-ref="music_2" />
23     </util:map>
24 
25 </beans>

可以看到spring-util.xsd模式文件定义了<util:map>元素,用于配置如何创建Map类型的集合。底下有个<entry>元素,用于配置字典集合的键值对。因此,这段配置创建了两个Map类型的集合:一个集合的id是utilMusicNameMap;一个集合的id是utilPlayingMusicMap。之后,把集合utilMusicNameMap注入music_2的musicNameMap属性,把集合utilPlayingMusicMap注入player的playingMusicMap属性,完成集合的注入。

延迟装配

按照正常流程,Spring容器完成Bean的创建之后,开始通过Bean的属性注入Bean的依赖,完成Bean的装配。可是有时候,我们并不希望Spring容器完成Bean的创建之后立即注入依赖,而是希望等到用到的时候才开始注入。这时,就需要用到延迟装配,告诉Spring容器等到用到Bean的时候,才开始注入Bean所需的依赖。如下所示:

1 <beans /* 省略命名空间和XSD模式文件声明 */>
2     <bean id="music" class="com.dream.Music" lazy-init="true">
3         <property name="musicName" value="执着"/>
4     </bean>
5     <bean id="player" class="com.dream.Player" lazy-init="true">
6         <property name="playingMusic" ref="music"/>
7     </bean>
8 </beans>

这段配置用到<bean>元素的lazy-init属性,用于告诉Spring容器需不需要延迟Bean的装配。如果lazy-init属性等于true,Spring容器创建Bean之后,只会等到用到Bean的时候才开始注入依赖;如果lazy-init属性等于false,Spring容器创建Bean之后,就会立即开始注入依赖。lazy-init属性默认等于false。这里,我们把lazy-init属性设为true,告诉Spring容器延迟装配music和player这两个Bean所需的依赖。

另外,我们还可设置根元素<beans>的default-lazy-init属性,告诉Spring容器所有的Bean都要延迟装配,如下所示:

1 <beans default-lazy-init="true" 
2        /* 省略命名空间和XSD模式文件声明 */>
3     <bean id="music" class="com.dream.Music">
4         <property name="musicName" value="执着"/>
5     </bean>
6     <bean id="player" class="com.dream.Player">
7         <property name="playingMusic" ref="music"/>
8     </bean>
9 </beans>

指定ID

一直以来,我们都用<bean>元素的id属性指定Bean的唯一标识符。可是我们不知道的是,除了id属性,我们也能使用name属性配置同样的信息。如下所示:

1 <bean id="music_1" name="music_2,music_3,music_4" class="com.dream.Music"/>

我们指定id属性的值为music_1,指定name属性的值为 music_2,music_3,music_4 。因此,该Bean具有四个唯一标识符:music_1,music_2,music_3和music_4。同时我们也注意到了,id属性和name属性有个重大差别:id属性只能指定一个唯一标识符;name属性则不同,可以同时指定多个唯一标识符,标识符之间只要使用逗号,分号或空格隔开就行。

除此之外,Spring还提供了<alias>元素,用于指定Bean的别名。如下所示:

1 <bean id="music_1" class="com.dream.Music"/>
2 <alias name="music_1" alias="music_2" />

<alias>元素具有name和alias两个属性:name属性用于指定Bean的唯一标识符;alias属性用于指定Bean的别名。因此,这段配置能够告诉Spring容器,给id为music_1的Bean起个别名music_2。之后,我们既可使用music_1,也可使用music_2引用该Bean

至此,我们完成了关于如何配置Bean的更多介绍。下章该谈谈自动装配时,Bean的歧义应该如何解决那些事了。欢迎大家继续阅读,谢谢大家!

返回目录    下载代码

posted @ 2022-01-31 23:16  林雪波  阅读(130)  评论(0编辑  收藏  举报