Spring中你不知道的注入方式

前言

    在Spring配置文件中使用XML文件进行配置,实际上是让Spring执行了相应的代码,例如:

  • 使用<bean>元素,实际上是让Spring执行无参或有参构造器
  • 使用<property>元素,实际上是让Spring执行一次setter方法

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

  • 调用getter方法:使用PropertyPathFactoryBean
  • 调用类或对象的Filed值:使用FiledRetrievingFactoryBean
  • 调用普通方法:使用MethodInvokingFactoryBean

注入其他Bean的属性值

    PropertyPathFactoryBean用来获得目标Bean的属性值(实际上就是调用getter方法返回的值),获得的值可以注入给其他的Bean,也可以直接定义新的Bean。看如下的配置文件:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<bean id="person" class="com.abc.Person">

    <property name="age" value="30" />

    <property name="son">

        <!-- 使用嵌套Bean定义属性值 -->

        <bean class="com.abc.service.Son">

            <property name="age" value="11" />

        </bean>

    </property>

</bean>

 

<bean id="son2" class="com.abc.service.Son">

    <!-- age属性不是直接注入,而是将person中的son的age属性赋值给son2的age属性 -->

    <property name="age">

        <!-- 注意这里使用的是PropertyPathFactoryBean -->

        <bean id="person.son.age" 

            class="org.springframework.beans.factory.config.PropertyPathFactoryBean" />

    </property>

</bean>

    其中Person类和Son类的属性可以从配置文件中看出,这不再给出。主程序如下:

?


1

2

3

4

5

6

7

public class Test {

    public static void main(String args[]) {

        ApplicationContext ac = 

            new ClassPathXmlApplicationContext("applicationContext.xml");

        System.out.println("age=" + ac.getBean("son2", Son.class).getAge());

    }

}

    输出结果:

?


1

age=11

    Bean实例的属性值,不仅可以注入另一个Bean,还可将Bean实例的属性值直接定义成Bean实例,这也是通过PropertyPathFactoryBean完成的。对上面的配置文件增加这样一段:

?


1

2

3

4

5

6

7

<bean id="son1" 

    class="org.springframework.beans.factory.config.PropertyPathFactoryBean">

    <!-- 确定目标Bean,表明son1来自哪个Bean的组件 -->

    <property name="targetBeanName" value="person" />

    <!-- 确定属性,表明son1来自目标Bean的哪个属性 -->

    <property name="propertyPath" value="son" />

</bean>

    执行上面的Test类,把son2换成son1,结果一样。

注入其他Bean的Field值

    通过FieldRetrievingFactoryBean类,可以将其他Bean的Field值注入给其他Bean,或者直接定义新的Bean。下面是配置片段:

?


1

2

3

4

5

6

<bean id="son" class="com.abc.service.Son">

    <property name="age">

        <bean id="java.sql.connection.TRANSACTION_SERIALIZABLE"

            class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />

    </property>

</bean>

    测试主程序与上文定义的类似,这里不再提供,执行结果如下:

?


1

age=8

    在这个配置中,son对象的age的值,等于java.sql.Connection.TRANSACTION_SERIALIZABLE的值。在上面的定义中,定义FieldRetrievingFactoryBean工厂Bean时,指定的id并不是该Bean实例的唯一标识,而是指定Field的表达式(即将要被取出来的值)。

    注意:Field既可以是静态的,也可以是非晶态的。上面的配置片段指定的Field表达式是静态Field值,因此可以通过类名直接访问。如果Field值是非静态的,则应该通过容器中已经存在的Bean来访问——即Field表达式的第一个短语应该是容器中已经存在的Bean。

    Field值也可以定义成Bean实例,例如,在配置文件中增加下面一段:

?


1

2

3

4

5

6

7

<bean id="age" 

    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">

    <!-- targetClass指定Field所在的目标类 -->

    <property name="targetClass" value="java.sql.Connection" />

    <!-- targetField指定Field名 -->

    <property name="targetField" value="TRANSACTION_SERIALIZABLE" />

</bean>

    在主程序中增加如下输出:

?


1

System.out.println("age=" + ac.getBean("age"));

    执行结果和上文一样。

    使用FieldRetrievingFactoryBean获取Field值时,必须指定如下两个属性:

  • targetClass或targetObject:分别用于指定Field值所在的目标累或目标对象。如果需要获得的Field是静态的,则使用targetClass指定目标累;如果Field是非静态的,则使用targetObject指定目标对象
  • targetField:指定目标类或目标对象的Field名

    如果Field是个静态Field,则有一种更加简洁的写法:

?


1

2

3

4

5

<bean id="age" 

    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">

    <!-- value指定哪个类的哪个静态域值 -->

    <property name="staticField" value="java.sql.Connection.TRANSACTION_SERIALIZABLE" />

</bean>


注入其他Bean的方法返回值

    通过MethodInvokingFactoryBean工厂Bean,可将目标方法的返回值注入为Bean的属性值。这个工厂Bean用来获取指定方法的返回值,该方法既可以是静态方法,也可以是实例方法;这个值既可以被注入到指定Bean实例的指定属性,也可以直接定义成Bean实例。看例子:

?


1

2

3

4

5

6

7

8

9

10

11

<bean id="valueGenerator" class="com.abc.util.ValueGenerator" />

<bean id="son1" class="com.abc.service.Son">

    <property name="age">

        <!-- 获取方法返回值:调用valueGenerator的getValue方法 -->

        <bean 

            class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

            <property name="targetObject" ref="valueGenerator" />

            <property name="targetMethod" value="getValue" />

        </bean>

    </property>

</bean>

    下面是ValueGenerator:

?


1

2

3

4

public class ValueGenerator {

    public int getValue() { return 2; }

    public static int getStaticValue () { return 3;}

}

    测试程序依旧打印son1中age的值,代码略,结果如下:

?


1

age=2

    如果要调用静态方法,则把配置修改为:

?


1

2

3

4

5

6

7

8

9

10

<bean id="son1" class="com.abc.service.Son">

    <property name="age">

        <!-- 获取方法返回值:调用valueGenerator的getStaticValue方法 -->

        <bean 

            class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

            <property name="targetClass" value="com.abc.util.ValueGenerator" />

            <property name="targetMethod" value="getStaticValue" />

        </bean>

    </property>

</bean>

    测试结果为:

?


1

age=3

    由于Java是支持重载的,只给定方法名,还不足以能够确定调用哪个方法,通过上面的配置能调用成功是因为ValueGenerator中的两个方法都没有参数。如果方法中有参数,该如何配置呢?在配置文件中加入以下内容:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<bean id="sysProps" 

    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

    <property name="targetClass" value="java.lang.System" />

    <property name="targetMethod" value="getProperties" />

<bean>

<bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

    <!-- 指向上面的sysProps Bean -->

    <property name="targetObject" value="sysProps" />

    <property name="targetMethod" value="getProperty" />

    <!-- 这里配置参数 -->

    <property name="arguments">

        <!-- 使用list元素列出调用方法的多个参数 -->

        <list>

            <value>java.version</value>

        </list>

    </property>

<bean>

    上例中相当于用"java.version"作为参数调用了java.lang.System的getProperty方法,返回值将创建一个名为javaVersion的Bean。即相当于:

?


1

javaVersion = java.lang.System.getProperty("java.version");

    和前文中的Field一样,如果要调用的方法为静态方法,也有一种更加简洁的方法:

?


1

2

3

4

5

<bean id="myBean"

    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

    <!-- 使用staticMethod属性,直接指定目标类的目标方法 -->

    <property name="staticMethod" value="com.abc.util.ValueGenerator.getStaticValue" />

</bean>

时间: 2024-12-23 18:38:27

Spring中你不知道的注入方式的相关文章

详析Spring中依赖注入的三种方式_java

前言 平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是"控制反转",通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做. 在Sprin

Spring中属性注入详解_java

本文演示了int.String.数组.list.set.map.Date等属性的注入. 其中Date类型的注入则是借助了Spring提供的属性编辑器来实现的,首先是用到的五个实体类 package com.jadyer.model; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; /** * 常见属性的注入 * @see 包括int,String,Array,lis

Spring中接口注入的三种方式

Type1 接口注入 我们常常借助接口来将调用者与实现者分离.如: public class ClassA { private InterfaceB clzB; public init() { Ojbect obj = Class.forName(Config.BImplementation).newInstance(); clzB = (InterfaceB)obj; } -- } 上面的代码中,ClassA依赖于InterfaceB的实现,如何获得InterfaceB实现类的实例?传统的方法

Spring中bean注入前后的一些操作:

InitializingBean 和 DisposableBean init-method 和 destroy-method @PostConstruct 和 @PreDestroy In Spring, InitializingBean and DisposableBean are two marker interfaces, a useful way for Spring to perform certain actions upon bean initialization and dest

【SSH系列】深入浅出spring IOC中三种依赖注入方式

spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入和控制反转是一样的概念吗?接触新的知识,小编的脑袋中全是大大的问号,不过没有关系,今天这篇博文,小编主要来简单的介绍一下在spring IOC中依赖注入的方法. 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性.我们可以从以下几个方面理解: a.参与者都

对于一个项目中的部分实体类不使用spring作为管理容器,也不使用注入方式来调用接口的话,如何手动处理实体类和调用接口?

问题描述 本人初学spring,对spring不甚了解.看到其他人做的web项目设计,说对action实体类不使用spring管理容器,也不使用注入方式来调用接口,手工处理.我想问大家的是,如果这样子的话,代码应该是怎样的方式?以下面这几个文件为例,使用spring管理实体类,并通过注入方式调用接口,现在是可以正常运行的,如果实现他说的这样,代码大致该如何修改呢?请大家详细指点,谢谢!!action类:packagecn.gth.test.view;importcn.gth.test.dao.I

详解Spring事务Transaction配置的五种注入方式

前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. 总结如下: Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSource.TransactionManager这两部分只是会根据数据访问方式有所变化,

Spring两种依赖注入方式的比较

       我们知道,Spring对象属性的注入方式有两种:设值注入和构造注入.先看代码: 假设有个类为People,该对象包含三个属性,name和school还有age,这些属性都有各自的setter和getter方法,还有一个包含这三个属性的构造方法.如果用spring来管理这个对象,那么有以下两种方式为People设置属性: 1.设值注入: ? 1 2 3 4 5 6 <bean id="people" class="com.abc.People"&g

Spring 依赖注入方式详解

阅读目录 1.Set注入 2.构造器注入 3.静态工厂的方法注入 4.实例工厂的方法注入 5.总结    平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是"控制反转",通俗的理解是:平常我们new一个实例,这个实例的控制权是我