上一篇做了IOC和AOP的原理介绍,这一篇主要讲解IOC的注入。不过我依然困惑一个问题:
一 : 依赖注入(DI)中有三种注入方式,那Spring中到底实现了几种方式?也是三种?
IOC在很多框架中都有实现,并不是Spring特有的,之前说过IOC主要包含DL(Dependency Lookup)和DI(Dependency Injection),也就是说实现IOC的技术有很多,但是主要包含DI和DL,但是相对而言,DI应用范围比较广泛,我想这也是为什么Martin Fowler将控制反转用依赖注入来代替的原因;在具体的应用中DI主要实现了接口注入(Type1 IOC),setter注入(Type2 IOC),构造器注入(Type3 IOC)这三种方式,在Spring的IOC设计中,实现了设值注入和构造注入,也是最主要的注入方式(也就是说Spring中还有其它注入方式),貌似目前并没有实现接口注入这一方法,但是在另一框架Avalon却实现了。
也就是说:1.依赖注入(DI)有三种注入方式:接口注入(Type1 IOC),设值注入(Type2 IOC),构造注入(Type3 IOC)
2.在Spring中IOC主要是DI实现,DI实现了设值注入和构造注入,但是Spring的IOC中除了依赖注入方式,还有其它注入方式。
3.所有javaEE框架的IOC实现,主要是上是基于DI的接口注入(Type1 IOC),setter注入(Type2 IOC),构造器注入(Type3 IOC)这三种方式实现
那么既然Spring中IOC主要用设值注入和构造注入实现,就先实现这两种:
设值注入(setter注入):
<!-- 采用设值注入方式 -->
<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"/>
package examples;
public class ExampleBean {
private AnotherBean beanOne; //第一个java bean
private YetAnotherBean beanTwo;// 第二个java bean
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;
}
}
构造注入:
<!-- 采用构造注入方式 -->
<bean id="exampleBean" class="examples.ExampleBean">
<!-- constructor injection using the nested <ref/> element -->
<constructor-arg>
<ref="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"/>
package examples;
public class ExampleBean {
private AnotherBean beanOne; //第一个java bean
private YetAnotherBean beanTwo;// 第二个java bean
private int i;// 一个整形变量
public ExampleBean(
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
this.beanOne = anotherBean;
this.beanTwo = yetAnotherBean;
this.i = i;
}
}
除了这两种以外,还可以使用静态工厂方法和实例工厂方法进行注入
静态工厂方法:
-----------我们除了使用DI进行注入之外,还可以使用其它方法返回对象实例---------------
<!-- 采用静态工厂方法返回对象实例 -->
<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"/>
public class ExampleBean {
// a private constructor
private 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;
}
}
实例工厂方法:
<!-- 使用实例工厂方法实例化 -->
<bean id="exampleBean" factory-bean="instanceFactory"
factory-method="createInstance">
<constructor-arg ref="anotherExampleBean"/>
<constructor-arg ref="yetAnotherBean"/>
<constructor-arg value="1">
</bean>
<bean id="instanceFactory" class="examples.exampleBean"/>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {
// a private constructor
private ExampleBean(...) {
...
}
public ExampleBean createInstance (
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
ExampleBean eb = new ExampleBean (...);
// some other operations...
return eb;
}
}
请注意,传给
静态工厂方法的参数由
constructor-arg元素提供,这与使用构造器注入时完全一样。而且,重要的是,工厂方法所返回的实例的类型并不一定要与包含
static工厂方法的类类型一致。尽管在此例子中它的确是这样。非静态的实例工厂方法与此相同(除了使用
factory-bean属性替代
class属性外)。
参考资料:《Spring技术内幕》,《Dependency Injection》
Spring官方手册:http://docs.spring.io/spring/docs/
欢迎共同探讨Spring技术,后面有时间会继续更新,希望能够不断完善,出现的错误非常欢迎指正