Technorati 标记: , , ,

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

    依赖注入主要有两种方式:构造器注入set注入

一、构造器注入

    构造器注入就是指指带有参数的构造函数注入,如下:

public class SimpleMovieLister {	//注入对象movieFinder	private MovieFinder movieFinder;	//通过构造器注入movieFinder	public SimpleMovieLister(MovieFinder movieFinder) {		this.movieFinder = movieFinder;	}	//省略其他使用movieFinder的业务逻辑}

    现在来考虑一下由构造参数引来的问题,如果构造参数也是ioc容器里一个bean,那比较好办,如下:

package x.y;public class Foo {  public Foo(Bar bar, Baz baz) {      // ...  }}

    以上构造函数并不存在模糊的地方,可以直接在xml配置文件使用<constructor-arg />来声明,而不需要声明参数的索引或者类型:

    如果是使用索引 ref,其类型是可以推断出来的。可是如果使用的是基本的数据类型或者string,如47,那spring是无法判断得出”47“是什么类型,如下:

package examples;public class ExampleBean {	private int month;	private String year;		public ExampleBean(int month, String year) {		this.month = month;		this.year = year;	}}
 

    同样能够想到的是根据参数的索引来赋值,如下:

     另外,还有第三种方式,就是根据参数名来指定赋值,如下:

二、Set注入

    set注入,其实就是不通过构造器来注入,而是通过set方法来注入。其使用与构造器注入类似,如下:

public class SimpleMovieLister {  // 需要注入的对象 movieFinder  private MovieFinder movieFinder;  // 使用set方法注入 movieFinder  public void setMovieFinder(MovieFinder movieFinder) {      this.movieFinder = movieFinder;  }  //省略其他使用 movieFinder 的业务逻辑}

三、依赖注入的Example

    1、如下是一个基于set注入的Demo,

public class ExampleBean {  private AnotherBean beanOne;  private YetAnotherBean beanTwo;  private int i;  public void setBeanOne(AnotherBean beanOne) {      this.beanOne = beanOne;  }  public void setBeanTwo(YetAnotherBean beanTwo) {      this.beanTwo = beanTwo;  }  public void setIntegerProperty(int i) {      this.i = i;  }}

    其对应的xml配置文件如下:

    依然值得提醒的是,set注入使用property来注入依赖对象.现在我们来对比一下与构造器注入的区别:

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;  }}

    现在来看一下构造器注入 的xml配置文件文件:

    值得提醒的是,构造器注入使用constructor-arg 来注入依赖对象.尽管构造器注入好set注入是最为常用的两种方法,我们也依然需要了解一下其他的方法,静态工厂注入和实例工厂注入,这两种方法的使用比较类似,现在只谈一下静态工厂的注入,如下:
public class ExampleBean {  //私有构造器,和上文一样  private ExampleBean(...) {    ...  }  // 静态工厂注入,注意此方法必须是静态的  public static ExampleBean createInstance (          AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {      ExampleBean eb = new ExampleBean (...);      //可以有选择的添加一些其他逻辑      return eb;  }}
    同时看一下其xml配置文件,注意的是静态工厂注入也是使用constructor-arg 来注入依赖对象,如下: