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. SSMS2008插件开发(2)--Microsoft Visual Studio 2008插件开发介绍

    原文:SSMS2008插件开发(2)--Microsoft Visual Studio 2008插件开发介绍 由于开发SSMS2008插件是通过VS2008进行的,有必要先介绍一下VS2008的插件开 ...

  2. vs2010下载链接中国简体(中国含msdn)

    昨天一个朋友说vs2010中国版可下载,我开始不相信.只是周末.所以,我下载一试 果然,安装了中国版,原本msdn订户才能够下载,感谢朋友们上传. 文件名 cn_visual_studio_2010_ ...

  3. 微软Visual Studio "14" CTP 2 发布

    微软Visual Studio "14" CTP 2 发布 对于在微软阵营下进行工作的团队来说,拥有最新版本的Visual Studio是提高效率最佳的选择,没有之一. 在本文中, ...

  4. asp.net MVC中的AppendTrailingSlash以及LowercaseUrls

    asp.net MVC中的AppendTrailingSlash以及LowercaseUrls asp.net MVC是一个具有极大扩展性的框架,可以在从Url请求开始直到最终的html的渲染之间进行 ...

  5. SpringMVC实现注解式权限验证

    SpringMVC学习系列(9) 之 实现注解式权限验证 对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servle ...

  6. Java编程思想笔记(第二章)

    第二章  一切都是对象 尽管Java是基于C++的,但相比之下,Java是一种更纯粹的面向对象程序设计语言. c++和Java都是杂合型语言(hybird language) 用引用(referenc ...

  7. NoSql数据库使用

    NoSql数据库使用半年后在设计上面的一些心得 NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么 ...

  8. iOS基础 - UIDatePicker and UIPickerView and UITextField

    1.UIDatePicker继承自UIControl,因此不会通过代理来监听事件的改变,而是通过addTarget来监听事件.监听的事件是值改变事件. 2.UIPickerView继承自UIView, ...

  9. 修改Ubuntu Server的分辨率

    修改Ubuntu Server的分辨率,其实就是找到关键的文件,然后修改参数,重启一下,就可以看见效果了. 1.打开文件并修改参数 文件位置:/etc/default/grub 修改位置:GRUB_C ...

  10. SQL Server的数据加密简介

    防止开发人员获取到敏感数据(SQL Server的数据加密简介) 背景 有时候,我们还真的会碰到这样的需求:防止开发人员获取到敏感数据.也许你觉得很简单,把开发和运营分开不就可以了吗?是的,如果公司有 ...