360SDN.COM

Spring Framework 5 权威指南(9)

来源:程序员阮威  2017-09-11 13:23:22    评论:0点击:

这是一个Spring 5专题系列,其诞生的动机是:

1.介绍最新版本的Spring Framework;

2.介绍最系统化的Spring Framework;

3.介绍最佳实践的Spring Framework;

   7.Dependencies

依赖注入(DependencyInjection)也叫控制反转(Inversion of Control),控制反转的意思是,bean对象不再自己控制其依赖的定位和实例化,而是bean在被实例化后由容器对其进行初始化注入其依赖。

依赖注入主要有两种方式:基于构造函数的依赖注入和基于设置方法的依赖注入。可以混合使用两种依赖注入的方式。一种好的做法是,必须的依赖使用基于构造函数的依赖注入,可选的依赖使用基于设置方法的依赖注入。前者也是Spring团队提倡的方式。

下面这个类只能使用基于构造函数的依赖注入:

public class SimpleMovieLister{

 

       // the SimpleMovieLister has a dependencyon a MovieFinder

       private MovieFinder movieFinder;

 

       // a constructor so that the Springcontainer can inject a MovieFinder

       public SimpleMovieLister(MovieFinder movieFinder) {

                this.movieFinder= movieFinder;

       }

 

       // business logic that actually uses theinjected MovieFinder is omitted...

 

}

构造函数的参数使用类型进行匹配注入,在没有歧义的情况下,无需指定参数type或者index,例如:

package x.y;

 

public class Foo{

 

       public Foo(Bar bar, Baz baz) {

                //...

       }

 

}

依赖注入配置如下即可:

<beans>

       <bean id="foo" class="x.y.Foo">

                <constructor-arg ref="bar"/>

                <constructor-arg ref="baz"/>

       </bean>

 

       <bean id="bar" class="x.y.Bar"/>

 

       <bean id="baz" class="x.y.Baz"/>

</beans>

如果构造函数的参数是基本类型(无法推断类型),则需要指定参数type

package examples;

 

public class ExampleBean{

 

       // Number of years to calculate theUltimate Answer

       private int years;

 

       // The Answer to Life, the Universe, andEverything

       private String ultimateAnswer;

 

       public ExampleBean(int years, String ultimateAnswer) {

                this.years= years;

                this.ultimateAnswer= ultimateAnswer;

       }

 

}

依赖注入配置如下:

<bean id="exampleBean" class="examples.ExampleBean">

       <constructor-arg type="int"value="7500000"/>

       <constructor-arg type="java.lang.String"value="42"/>

</bean>

如果按照类型匹配存在歧义(类型相同),则可以直接指定参数index

<bean id="exampleBean" class="examples.ExampleBean">

       <constructor-arg index="0" value="7500000"/>

       <constructor-arg index="1" value="42"/>

</bean>

直接指定构造函数的参数name,也可以消除歧义:

<bean id="exampleBean" class="examples.ExampleBean">

       <constructor-arg name="years" value="7500000"/>

       <constructor-arg name="ultimateAnswer" value="42"/>

</bean>

要使这种方式能工作,代码必须以debug模式进行编译(javac-g),或者使用JDK提供的@ConstructorProperties注解显式的命名构造函数参数,如下:

package examples;

 

public class ExampleBean{

 

       // Fields omitted

 

       @ConstructorProperties({"years", "ultimateAnswer"})

       public ExampleBean(int years, String ultimateAnswer) {

                this.years= years;

                this.ultimateAnswer= ultimateAnswer;

       }

 

}

下面这个类只能使用基于设置方法的依赖注入:

public class SimpleMovieLister{

 

       // the SimpleMovieLister has a dependencyon the MovieFinder

       private MovieFinder movieFinder;

 

       // a setter method so that the Springcontainer can inject a MovieFinder

       public void setMovieFinder(MovieFinder movieFinder) {

                this.movieFinder= movieFinder;

       }

 

       // business logic that actually uses theinjected MovieFinder is omitted...

 

}

看一个基于设置方法的依赖注入的例子:

public class ExampleBean {

 

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

 

    publicvoidsetBeanOne(AnotherBean beanOne) {

       this.beanOne = beanOne;

    }

 

    publicvoidsetBeanTwo(YetAnotherBean beanTwo) {

       this.beanTwo = beanTwo;

    }

 

    publicvoidsetIntegerProperty(int i) {

       this.i = i;

    }

 

}

依赖注入配置如下:

<bean id="exampleBean"class="examples.ExampleBean">

   <!--setter injection using the nested ref element -->

    <property name="beanOne">

       <ref bean="anotherExampleBean"/>

    </property>

 

    <!--setter injection using the neater ref attribute -->

    <property name="beanTwo" ref="yetAnotherBean"/>

    <property name="integerProperty" value="1"/>

</bean>

 

<bean id="anotherExampleBean" class="examples.AnotherBean"/>

<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

将上面的例子改成基于构造函数的依赖注入:

public class ExampleBean {

 

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

 

    public ExampleBean(

       AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

       this.beanOne = anotherBean;

       this.beanTwo = yetAnotherBean;

       this.i = i;

    }

 

}

依赖注入配置如下:

<bean id="exampleBean" class="examples.ExampleBean">

    <!--constructor injection using the nested ref element -->

    <constructor-arg>

       <ref bean="anotherExampleBean"/>

    </constructor-arg>

 

    <!--constructor injection using the neater ref attribute -->

    <constructor-arg ref="yetAnotherBean"/>

 

    <constructor-arg type="int" value="1"/>

</bean>

 

<bean id="anotherExampleBean" class="examples.AnotherBean"/>

<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

将上面的例子改成使用工厂方法进行实例化并进行依赖注入:

public class ExampleBean {

 

    // aprivate constructor

    private ExampleBean(...) {

       ...

    }

 

    // astatic factory method; the arguments to this method can be

    //considered the dependencies of the bean that is returned,

    //regardless of how those arguments are actually used.

    public static ExampleBean createInstance (

       AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

 

       ExampleBean eb = new ExampleBean (...);

       // some other operations...

       return eb;

    }

 

}

依赖注入配置如下:

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">

    <constructor-arg ref="anotherExampleBean"/>

    <constructor-arg ref="yetAnotherBean"/>

    <constructor-arg value="1"/>

</bean>

 

<bean id="anotherExampleBean" class="examples.AnotherBean"/>

<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

阅读原文

为您推荐

友情链接 |九搜汽车网 |手机ok生活信息网|ok生活信息网|ok微生活
 Powered by www.360SDN.COM   京ICP备11022651号-4 © 2012-2016 版权