7.10.1 获取其他Bean的属性值

7.10.1 获取其他Bean的属性值

PropertyPathFactoryBean用来获取目标Bean的属性值(实际上就是它的getter方法的返回值),获得的值可注入给其他Bean,也可直接定义成新的Bean
使用PropertyPathFactoryBean来调用其他Beangetter方法需要指定如下信息。

  • 调用哪个对象。由PropertyPathFactoryBeansetTargetObject(Object targetObject)方法指定
  • 调用哪个getter方法。由PropertyPathFactoryBeansetPropertyPath(String propertyPath)方法指定。

程序示例

项目结构

1
2
3
4
5
6
7
8
9
10
11
E:\workspace_QingLiangJiJavaEEQiYeYingYongShiZhang5\PropertyPathFactoryBean
└─src\
├─beans.xml
├─lee\
│ └─SpringTest.java
└─org\
└─crazyit\
└─app\
└─service\
├─Person.java
└─Son.java

beans.xml

看如下配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
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/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!--下面配置定义一个将要被引用的目标bean -->
<bean id="person" class="org.crazyit.app.service.Person">
<!-- 为setAge()方法指定参数值 -->
<property name="age" value="30" />
<property name="son">
<!-- 使用嵌套Bean为setSon()方法指定参数值 -->
<bean class="org.crazyit.app.service.Son">
<property name="age" value="11" />
</bean>
</property>
</bean>
<!-- 将指定Bean实例的getter方法返回值定义成son1 Bean -->
<bean id="son1"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<!-- 指定来自哪个Bean -->
<property name="targetBeanName" value="person" />
<!-- 指定来自哪个getter方法,son代表getSon() -->
<property name="propertyPath" value="son" />
<!-- 这两个属性组合起来就是`son1`这个Bean来自person这个bean的getSon()方法 -->
</bean>
<beans>

SpringTest.java

主程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package lee;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest
{
public static void main(String[] args)
{
@SuppressWarnings("resource")
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"beans.xml");
System.out.println("系统获取的son1:" + ctx.getBean("son1"));
}
}

执行结果如下:

1
系统获取的son1:Son[age=11]

上面配置文件使用PropertyPathFactoryBean来获取指定Bean的、指定getter方法的返回值,如下代码:

1
2
3
4
5
6
7
8
9
<!-- 将指定Bean实例的getter方法返回值定义成son1 Bean -->
<bean id="son1"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<!-- 指定来自哪个Bean -->
<property name="targetBeanName" value="person" />
<!-- 指定来自哪个getter方法,son代表getSon() -->
<property name="propertyPath" value="son" />
<!-- 这两个属性组合起来就是`son1`这个Bean来自person这个bean的getSon()方法 -->
</bean>

指定了获取person这个BeangerSon()方法的返回值,然后将返回值直接定义成容器中idson1Bean.

PropertyPathFactoryBean就是工厂Bean,关于工厂Bean的介绍可参考7.8.3节的内容,工厂Bean专门返回某个类型的值,并不是返回该Bean的实例。

PropertyPathFactoryBean的工厂Bean的id属性是属性表达式的值

注意:配置PropertyPathFactoryBean工厂Bean时指定的id属性,并不是该工厂Bean的唯一标识,而是用于指定属性表达式的值,可以对该属性表达式的值进行简写,例如:将该工厂Beanid属性设置为person.son.age则表示person.getSon().getAge()的返回值作为一个Bean.

1
2
3
<!-- 以下是访问指定Bean的getter方法的简单方式, person.son.age代表获取person.getSon().getAge() -->
<bean id="person.son.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean" />

Spring获取指定Beangetter方法的返回值之后,该返回值不仅可直接定义成容器中的Bean实例,还可注入另一个Bean作为成员变量
对上面的配置文件增加如下一段。

1
2
3
4
5
6
7
8
9
<!-- 下面定义son2 Bean -->
<bean id="son2" class="org.crazyit.app.service.Son">
<property name="age">
<!-- 使用嵌套Bean为调用setAge()方法指定参数值 -->
<!-- 以下是访问指定Bean的getter方法的简单方式, person.son.age代表获取person.getSon().getAge() -->
<bean id="person.son.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean" />
</property>
</bean>

主程序部分增加如下的输出语句:

1
System.out.println("系统获取的son2:" + ctx.getBean("son2"));

运行主程序,此输出语句的执行结果如下:

1
系统获取的son2:Son[age=11]

从上面的粗体字代码可以看出,程序调用son2实例的setAge()方法时的参数并不是直接指定的,而是将容器中另一个Bean实例的属性值( getter方法的返回值)作为setAge()方法的参数,PropertyPathFactoryBean工厂Bean负责获取容器中另一个Bean的属性值(getter方法的返回值)

使用复合形式设置getter方法

PropertyPathFactoryBeansetPropertyPath()方法指定属性表达式时,还支持使用复合属性的形式,例如:想获取person BeangetSon().getAge()的返回值,可采用son.age的形式.

在配置文件中再增加如下一段:

1
2
3
4
5
6
7
8
<!-- 将基本数据类型的属性值定义成Bean实例 -->
<bean id="theAge"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<!-- 确定目标Bean-->
<property name="targetBeanName" value="person" />
<!-- 使用复合属性来指定getter方法。son.age代表getSon().getAge() -->
<property name="propertyPath" value="son.age" />
</bean>

主程序部分增加如下输出语句:

1
System.out.println("系统获取的theAge的值:" + ctx.getBean("theAge"));

该条语句输出结果如下:

1
系统获取的theAge的值:11

以嵌套的Bean实例作为目标Bean

目标Bean既可以是容器中已有的Bean实例,也可以是嵌套Bean实例。因此,下面的定义也是有效的。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 将基本数据类型的属性值定义成Bean实例 -->
<bean id="theAge2"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<!-- 确定目标Bean,此处采用嵌套Bean定义目标Bean -->
<property name="targetObject">
<!-- 目标Bean是嵌套Bean -->
<bean class="org.crazyit.app.service.Person">
<property name="age" value="30" />
</bean>
</property>
<!-- 确定getter方法,age代表getAge() -->
<property name="propertyPath" value="age" />
</bean>

util:property-path元素

<util:property-path>元素可作为PropertyPathFactoryBean的简化配置,使用该元素时可指定如下两个属性。

属性 描述
id 该属性指定将getr方法的返回值定义成名为i的Bean实例。
path 该属性指定将哪个Bean实例、哪个属性(支持复合属性)暴露出来

如果需要使用<util:property-path>元素,则必须在Spring配置文件中导入util:命名空间。关于导入util:命名空间的详细步骤请参考7.11.3节。
上面的son1这个Bean

1
2
3
4
5
<bean id="son1"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="person" />
<property name="propertyPath" value="son" />
</bean>

可简化为如下配置:

1
<util:property-path id="son1" path="person.son"/>

上面的son2这个Bean:

1
2
3
4
5
6
<bean id="son2" class="org.crazyit.app.service.Son">
<property name="age">
<bean id="person.son.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean" />
</property>
</bean>

可简化为如下配置:

1
2
3
4
5
<bean id="son2" class="org.crazyit.app.service.Son">
<property name="age">
<util:property-path path="person.son.age" />
</property>
</bean>