基于构造器(或静态工厂方法)的依赖注入
基于构造器的注入:容器通过调用指定参数的构造器完成bean的实例化,并且通过构造器的参数完成依赖注入。(静态工厂方法与构造器的行为基本一致)
举例:
public class SimpleMovieLister {// the SimpleMovieLister has a dependency on a MovieFinderprivate MovieFinder movieFinder;// a constructor so that the Spring container can inject a MovieFinderpublic SimpleMovieLister(MovieFinder movieFinder) {this.movieFinder = movieFinder;}// business logic that actually uses the injected MovieFinder is omitted...
}
构造器参数解析:容器调用“哪一个”构造器。
策略:通过类型匹配。通过构造器注入时,根据传入的参数的类型,匹配构造器,如果找不到,就会报错。
Java代码:
package SpringTest.ConBasedDI;public class TestConDI {public TestConDI(ConArgOne arg1, ConArgOne arg2) {System.out.println("TestConDI(ConArgOne, ConArgOne)");}public TestConDI(ConArgOne arg1, ConArgTwo arg2){System.out.println("TestConDI(ConArgOne, ConArgTwo)");}public TestConDI(ConArgTwo arg1, ConArgOne arg2) {System.out.println("TestConDI(ConArgTwo, ConArgOne)"); }
}
当启动容器时,运行结果:
匹配时,根据多个constructor-arg子标签指定多个参数类型,子标签的顺序匹配构造器参数的顺序。
使用index属性调整顺序,如果没有用使用index属性,则默认是按照标签排列的顺序进行匹配,如果设置了index属性,则按照index值(从0开始)进行匹配
相当于
参数继承问题
对于上面这个例子,没有让ConArgOne和ConArgTwo具有继承关系。
如果让ConArgTwo继承ConArgOne呢?
运行结果没有变化。
请注意这个配置
继承之后TestConDI(ConArgOne, ConArgOne) 和 TestConDI(ConArgOne, ConArgTwo)都符合这个配置,但还是调用了TestConDI(ConArgOne, ConArgTwo)。
如果有多个选择,容器会帮我们匹配类型更精确的。
确定简单值的类型。
对于引用类型,匹配构造器的时候根据引用的bean类型即可。但是对于简单类型来说,并不能确定它的类型。
举个例子:
package examples;public class ExampleBean {// Number of years to calculate the Ultimate Answerprivate int years;// The Answer to Life, the Universe, and Everythingprivate String ultimateAnswer;public ExampleBean(int years, String ultimateAnswer) {this.years = years;this.ultimateAnswer = ultimateAnswer;}
}
按照上面的配置方法,可以这样配置。
可以看到,简单的使用value属性是不能确定类型的。运行可能并不会出错
使用type属性指定类型:
使用name属性指定参数名:
举例(基于构造器注入 + 基于静态工厂方法注入)
基于构造器注入
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;}
}
基于静态工厂方法注入
public class ExampleBean {// a private constructorprivate ExampleBean(...) {...}// a static 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;}
}