平常的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配置文件文件:
public class ExampleBean { //私有构造器,和上文一样 private ExampleBean(...) { ... } // 静态工厂注入,注意此方法必须是静态的 public static ExampleBean createInstance ( AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { ExampleBean eb = new ExampleBean (...); //可以有选择的添加一些其他逻辑 return eb; }}