7.10 高级依赖关系配置

      组件与组件之间的耦合,采用依赖注入管理;但基本类型的成员变量值,应直接在代码中设置。

      Spring支持将任意方法的返回值、类或对象的Field值、其他Bean的getter方法返回值,直接定义成容器中的一个Bean。

      Spring框架的本质是,开发者在Spring配置文件中使用XML元素进行配置,实际驱动Spring执行响应的代码。例如:

      ⊙ 使用<bean.../>元素,实际启动Spring执行无参数或有参数的构造器,或者调用工厂方法创建Bean。

      ⊙ 使用<property.../>元素,实际驱动Spring执行一次setter方法。

      但Java程序还可能有其他类型的语句,如调用getter方法、调用普通方法、访问类或对象的Field,而Spring也为这种语句提供了对应的配置语法。例如:

      ⊙ 调用getter方法 :使用PropertyPathFactoryBean

      ⊙ 访问类或对象的Field值 : 使用FieldRetrievingFactoryBean。

      ⊙ 调用普通方法 : 使用MethodInvokingFactoryBean。

      7.10.1 获取其他Bean的属性值

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

        使用PropertyPathFactoryBean来调用其他Bean的getter方法需要指定如下信息:

        ⊙ 调用那个对象。有PropertyPathFactoryBean的setTargetObject(Object targetObject) 方法指定。

        ⊙ 调用那个getter方法。有PropertyPathFactoryBean的setPropertyPath(String propertyPath)方法指定。

        Class : Person

package edu.pri.lime._7_10_1.bean;

public class Person {

    private String name;
private int age;
private Person son; public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person getSon() {
System.out.println("father:getSon");
return son;
}
public void setSon(Person son) {
this.son = son;
} }

        XML :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="father" class="edu.pri.lime._7_10_1.bean.Person">
<property name="name" value="lime" />
<property name="age" value="45" />
<property name="son">
<bean class="edu.pri.lime._7_10_1.bean.Person">
<property name="name" value="oracle"/>
<property name="age" value="20" />
</bean>
</property>
</bean> <bean id="mother" class="edu.pri.lime._7_10_1.bean.Person">
<property name="name" value="liyu"/>
<property name="age" value="43"/>
<!-- 可以注入另一个Bean中 -->
<property name="son">
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<!-- 确定目标Bean,指定son Bean来自哪个Bean的getter方法 -->
<property name="targetBeanName" value="father"/>
<!-- 指定son Bean来自目标Bean的哪个getter方法,age代表getAge() -->
<property name="propertyPath" value="son"/>
</bean>
</property>
</bean> <!-- 可以直接定义成容器中的Bean实例 -->
<bean id="son" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="father"/>
<property name="propertyPath" value="son"/>
</bean>
</beans>

        Class : SpringTest

package edu.pri.lime._7_10_1.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import edu.pri.lime._7_10_1.bean.Person; public class SpringTest {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_10_1.xml"); // 可以注入到另一个Bean中
Person mother = ctx.getBean("mother",Person.class);
System.out.println(mother.toString());
System.out.println(mother.getSon().toString()); Person father = ctx.getBean("father",Person.class);
System.out.println(father.toString());
System.out.println(father.getSon().toString()); // 可以定义成容器中的Bean实例
Person son = ctx.getBean("son",Person.class);
System.out.println(son.toString());
}
}

        Console :

father:getSon
edu.pri.lime._7_10_1.bean.Person@776aec5c
father:getSon
edu.pri.lime._7_10_1.bean.Person@1d296da
edu.pri.lime._7_10_1.bean.Person@7c7a06ec
father:getSon
edu.pri.lime._7_10_1.bean.Person@1d296da
father:getSon
edu.pri.lime._7_10_1.bean.Person@1d296da

        程序调用son实例的setSon方法的参数并不是直接指定的,而是将容器中另一个Bean实例的属性值(getter方法的返回值)作为setSon()方法的参数。注意son Bean的地址是一样的。

        PropertyPathFactoryBean工厂Bean负责获取容器中另一个Bean的属性值(getter方法的返回值)。

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

        XML :

    <!-- 将基本数据类型的属性值定义成Bean实例 -->
<bean id="theAge" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<!-- 确定目标Bean,表明theAge Bean来自哪个Bean的getter方法的返回值 -->
<property name="targetBeanName" value="mother"/>
<!-- 使用复合属性来指定getter方法。son.age代表getSon().getAge() -->
<property name="propertyPath" value="son.age"/>
</bean>

        目标Bean既可以是容器中已有的Bean实例,也可以是嵌套Bean实例。

        使用嵌套Bean实例时,指定目标Bean使用targetObject属性,其他时候使用targetBeanName属性

        XML :

   <!-- 将基本数据类型的属性值定义成Bean实例 -->
<bean id="hisAge" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<!-- 确定目标Bean,表明hisAge Bean来自哪个Bean的属性。此处采用嵌套Bean定义目标Bean -->
<property name="targetObject">
<!-- 目标Bean不是容器中已经存在的Bean,而是如下的嵌套Bean -->
<!-- 使用嵌套Bean实例时,指定目标Bean使用targetObject属性,其他时候使用targetBeanName属性 -->
<bean class="edu.pri.lime._7_10_1.bean.Person">
<property name="age" value="30" />
</bean>
</property>
<!-- 指定hisAge Bean来自目标Bean 的哪个getter方法,age代表getAge() -->
<property name="propertyPath" value="age"/>
</bean>

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

          ⊙ id : 该属性指定将getter方法的返回值定义成名为id的Bean的实例。

          ⊙ path : 该属性指定将哪个Bean实例、哪个属性(支持复合属性)暴露出来。

        如果需要使用<util:property-path.../>元素,必须在Spring配置文件中导入util:命名空间。

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd">

        herAge 可简化为:

<util:property-path id="herAge" path="father.son.age"/>

      7.10.2 获取Field值

        通过FieldRetrievingFactoryBean类,可访问类的静态Field或对象的实例Field值。

        FieldRetrievingFactoryBean 获得指定Field的值之后,即可将获取的值注入其他Bean,也可直接定义成Bean。

        使用FieldRetrievingFactoryBean访问Field值可分为两种情形。

        ① 如果要访问的Field是静态Field,则需要指定:

          ⊙ 调用哪个类。由FieldRetrievingFactoryBean的setTargetClass(String targetClass)方法指定。

          ⊙ 访问哪个Field。由FieldRetrievingFactoryBean的setTargetField(String targetField)方法指定。

        ② 如果要访问的Field是实例Field,则需要指定:

          ⊙ 调用哪个对象。由FieldRetrievingFactoryBean的setTargetObject(Object targetObject)方法指定。

          ⊙ 访问哪个Field。由FieldRetrievingFactoryBean的setTargetField(String targetField)方法指定。

        对于FieldRetrievingFactory访问实例Field的情形,需要实例Field以public修饰,这种情况及其少见。

        XML :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 将指定类的静态Field值定义成容器中的Bean实例 -->
<bean id="theAge" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<!-- targetClass指定访问哪个目标类 -->
<property name="targetClass" value="java.sql.Connection"/>
<!-- targetField指定要访问的Field名 -->
<property name="targetField" value="TRANSACTION_SERIALIZABLE"/>
</bean> </beans>

        Class : SpringTest

package edu.pri.lime._7_10_2.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_10_2.xml");
{
Integer theAge = ctx.getBean("theAge",Integer.class);
System.out.println(theAge);
}
}
}

        Console :

一月 14, 2017 6:52:01 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2752f6e2: startup date [Sat Jan 14 18:52:01 CST 2017]; root of context hierarchy
一月 14, 2017 6:52:01 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [app_7_10_2.xml]
8

        FieldRetrievingFactoryBean还提供了一个setStaticField(String staticField)方法,该方法可同时指定获取哪个类的哪个静态Field值。

   <bean id="hisAge" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="staticField" value="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</bean>

        <util:constant.../>元素(需要导入util:命名空间)可作为FieldRetrievingFactoryBean访问静态Field的简化配置。

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd">

        使用<util:constant.../>元素需指定如下两个属性:

        ⊙ id : 该属性指定就爱那个静态Field的值定义成名为id 的Bean实例。

        ⊙ static-field : 该属性指定访问哪个类的哪个静态Field。

        herAge可简化为如下配置:

<util:constant id="herAge" static-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>

      7.10.3 获取任意方法的返回值

        通过MethodInvokingFactoryBean工程Bean,可调用任意类的类方法,也可调用任意对象的实例方法,如果调用的方法有返回值,即可将该指定方法的返回值定义成容器中的Bean,也可将指定方法的返回值注入给其他Bean。

        使用MethodInvokingFactoryBean来调用任意方法时,可分为两种情形。

        ① 如果希望调用的方法是静态方法,则需要指定:

          ⊙ 调用哪个类。通过MethodInvokingFactoryBean的setTargetClass(String targetClass)方法指定。

          ⊙ 调用哪个方法。通过MethodInvokingFactoryBean的setTargetMethod(String targetMethod)方法指定。

          ⊙ 调用方法的参数。通过MethodInvokingFactoryBean的setArguments(Object[] arguments)方法指定。

            如果希望调用的方法无须参数,则可以省略该配置。

        ② 如果希望调用的方法是实例方法,则需要指定:

          ⊙ 调用哪个对象。通过MethodInvokingFactoryBean的setTargetObject(Object targetObject)方法指定。

          ⊙ 调用哪个方法。通过MethodInvokingFactoryBean的setTargetMethod(String targetMethod)方法指定。

          ⊙ 调用方法的参数。通过MethodInvokingFactoryBean的setArguments(Object[] arguments)方法指定。

            如果希望调研那个的方法无须参数,则可以省略该配置。

        Class : SpringTest

package edu.pri.lime._7_10_3.main;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea; public class SpringTest { public static void main(String[] args){
JFrame win = new JFrame("我的窗口");
JTextArea jta = new JTextArea(7,40);
win.add(new JScrollPane(jta));
JPanel jp = new JPanel();
win.add(jp,BorderLayout.SOUTH);
JButton jb1 = new JButton("确定");
jp.add(jb1);
JButton jb2 = new JButton("取消");
jp.add(jb2);
win.pack();
win.setVisible(true);
}
}

        使用配置文件XML :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!--
下面配置相当于如下Java代码:
JFrame win = new JFrame("我的窗口");
win.setVisible(true); -->
<bean id="win" class="javax.swing.JFrame">
<constructor-arg value="我的窗口" type="java.lang.String"/>
<property name="visible" value="true"/>
</bean>
<!--
下面配置相当于如下Java代码:
JTextArea jta = JTextArea(7,40); -->
<bean id="jta" class="javax.swing.JTextArea">
<constructor-arg value="7"/>
<constructor-arg value="40"/>
</bean>
<!--
使用MethodInvokingFactoryBean驱动Spring调用普通方法下面配置相当于如下Java代码:
win.add(new JScrollPane(jta)); -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="win"/>
<property name="targetMethod" value="add"/>
<property name="arguments">
<array>
<bean class="javax.swing.JScrollPane">
<constructor-arg ref="jta"/>
</bean>
</array>
</property>
</bean>
<!--
下面配置相当于如下Java代码:
JPanel jp = new JPanel(); -->
<bean id="jp" class="javax.swing.JPanel"/>
<!--
使用MethodInvokingFactoryBean驱动Spring调用普通方法
下面配置相当于如下Java代码
win.add(jp,BorderLayout.SOUTH); -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="win"/>
<property name="targetMethod" value="add"/>
<property name="arguments">
<array>
<ref bean="jp"/>
<bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="targetClass" value="java.awt.BorderLayout"/>
<property name="targetField" value="SOUTH"/>
</bean>
<!--
<util:constant static-field="java.awt.BorderLayout.SOUTH"/>
-->
</array>
</property>
</bean>
<!--
下面配置相当于如下Java代码:
JButton jb1 = new JButton("确定"); -->
<bean id="jb1" class="javax.swing.JButton">
<constructor-arg value="确定" type="java.lang.String"/>
</bean>
<!--
使用MethodInvokingFactoryBean驱动Spring调用普通方法
下面配置相当于如下Java代码:
jp.add(jb1); -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jp"/>
<property name="targetMethod" value="add"/>
<property name="arguments">
<array>
<ref bean="jb1"/>
</array>
</property>
</bean>
<!--
下面配置相当于如下Java代码:
JButton jb2 = new JButton("取消"); -->
<bean id="jb2" class="javax.swing.JButton">
<constructor-arg value="取消" type="java.lang.String"/>
</bean>
<!--
使用MethodInvokingFactoryBean驱动Spring调用普通方法
下面配置相当于如下Java代码:
jp.add(jb2); -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jp"/>
<property name="targetMethod" value="add"/>
<property name="arguments">
<array>
<ref bean="jb2"/>
</array>
</property>
</bean>
<!--
使用MethodInvokingFactoryBean驱动Spring调用普通方法:
下面配置相当于如下Java代码:
win.pack(); -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="win"/>
<property name="targetMethod" value="pack"/>
</bean> </beans>

        Class : XMLTest

package edu.pri.lime._7_10_3.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class XMLTest {
@SuppressWarnings("resource")
public static void main(String[] args){
new ClassPathXmlApplicationContext("app_7_10_3.xml");
}
}

        Spring框架的本质其实就是通过XML配置来执行Java代码,因此几乎可以把所有的Java代码放到Spring配置文件中管理。

        归纳:

          ⊙ 调用构造器创建对象(包括使用工厂方法创建对象),用<bean.../>元素。

          ⊙ 调用setter方法,用<property.../>元素。

          ⊙ 调用getter方法,用PropertyPathFactoryBean或<util:property-path.../>元素。

          ⊙ 调用普通方法,用MethodInvokingFactoryBean工厂Bean。

          ⊙ 获取Field值,用FieldRetrievingFactoryBean或<util:constant.../>元素。

        一般来说,应该将如下两类信息放到XML配置文件中管理:

        ⊙ 项目升价、维护时经常需要改动的信息。

        ⊙ 控制项目内个组件耦合关系的代码。

        这样就体现了Spring IoC 容器的作用:将原来使用Java 代码管理的耦合关系,提取到XML中进行管理,从而降低了各组件之间的耦合,提高了软件系统的可维护性。

  

啦啦啦

      

       

7 -- Spring的基本用法 -- 10...的更多相关文章

  1. 7 -- Spring的基本用法 -- 10... 获取其他Bean的属性值;获取Field值;获取任意方法的返回值

    7.10 高级依赖关系配置 组件与组件之间的耦合,采用依赖注入管理:但基本类型的成员变量值,应直接在代码中设置. Spring支持将任意方法的返回值.类或对象的Field值.其他Bean的getter ...

  2. SpringMVC +mybatis+spring 结合easyui用法及常见问题总结

    SpringMVC +mybatis+spring 结合easyui用法及常见问题总结 1.FormatString的用法. 2.用postAjaxFillGrid实现dataGrid 把form表单 ...

  3. Spring Boot 1.5.10 发布:修复重要安全漏洞!!!

    2018/01/31,Spring Boot团队发布了Spring Boot 1.5.10. Maven: <parent> <groupId>org.springframew ...

  4. Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息

    </pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...

  5. Spring中@Async用法详解及简单实例

    Spring中@Async用法 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类 ...

  6. 7 -- Spring的基本用法 -- 5...

    7.5 Spring容器中的Bean 7.5.1 Bean的基本定义和Bean别名 <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性: default-la ...

  7. (转)Spring中@Async用法总结

     原文:http://blog.csdn.net/blueheart20/article/details/44648667 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的: ...

  8. Spring中@Async用法总结

    引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3. ...

  9. 7 -- Spring的基本用法 -- 12...

    7.12 Spring 3.0 提供的表达式语言(SpEL) Spring表达式语言(简称SpEL)是一种与JSP 2 的EL功能类似的表达式语言,它可以在运行时查询和操作对象图.支持方法调用和基本字 ...

随机推荐

  1. leetcode[164] Maximum Gap

    梅西刚梅开二度,我也记一题. 在一个没排序的数组里,找出排序后的相邻数字的最大差值. 要求用线性时间和空间. 如果用nlgn的话,直接排序然后判断就可以了.so easy class Solution ...

  2. NHibernate 数据查询之QueryOver<T>

    NHibernate 数据查询之QueryOver<T>   一.限制运算符 Where:筛选序列中的项目WhereNot:反筛选序列中的项目 二.投影运算符 Select:创建部分序列的 ...

  3. .NET MVC4 实训记录之六(利用ModelMetadata实现资源的自主访问)

    上一篇我们已经实现自定义资源文件的访问,该篇我们使用它配合ModelMetadata实现资源文件的自主访问.这样做是为了我们能更简单的用MVC原生的方式使用资源文件.由于我的文章旨在记录MVC项目的实 ...

  4. document对象属性documentMode与CompatMode

    DOCTYPE DOCTYPE全称Document Type Declaration(文档类型声明,缩写DTD) DTD的声明影响浏览器对于CSS代码及Javascript脚本的解析. 渲染模式 渲染 ...

  5. IDE编程环境

    Vim配置及说明——IDE编程环境 目录 Vim配置及说明——IDE编程环境 1.基本及字体 2.插件管理 3.主题风格 4.窗口设置 5.目录树导航 6.标签导航 7.taglist 8.多文档编辑 ...

  6. winform动态的文字效果

    效果图如下

  7. How To Configure Logging And Log Rotation In Apache On An Ubuntu VPS

    Introduction The Apache web server can be configured to give the server administrator important info ...

  8. start running 开始跑步减肥

    begin 两个月前,逛超市的时候站在体重秤上称了称,一直以为自己体重很正常(BMI<25,虽然也不轻~~~),结果直接迈过超重,奔着肥胖跑去了(BMI>30,BMI计算器 http:// ...

  9. EasyUI DataGrid及Pagination

    接上一篇EasyUI项目驱动学习 DataGrid数据表格及Pagination分页一起介绍 一.通过<table>标记创建DataGrid,嵌套<th>标签定义列表 < ...

  10. Http Module 介绍(转载)

    Http Module 介绍 引言 Http 请求处理流程 和 Http Handler 介绍 这两篇文章里,我们首先了解了Http请求在服务器端的处理流程,随后我们知道Http请求最终会由实现了IH ...