Spring2.5.6学习笔记-DI的两种注入方式
1. 构造器注入
通过带有参数的构造器来实现,每个参数代表着一个依赖
1.1 构造器参数解析
1.1.1 bean类型明确
package x.y; public class Foo { public Foo(Bar bar, Baz baz) { // ... } }
<beans> <bean name="foo" class="x.y.Foo"> <constructor-arg> <bean class="x.y.Bar"/> </constructor-arg> <constructor-arg> <bean class="x.y.Baz"/> </constructor-arg> </bean> </beans>
1.1.2 简单参数类型
通过type属性指定简单参数的类型
package examples; public class ExampleBean { // No. of years to the calculate the Ultimate Answer private int years; // The Answer to Life, the Universe, and Everything 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从0开始
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </bean>
2. Setter注入
2.1 通过调用无参构造器或无参静态工厂方法实例化bean后,调用该bean的setter方法即可实现基于setter的DI
3. 一些例子
3.1 用XML格式定义的Setter DI
<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 void setBeanOne(AnotherBean beanOne) { this.beanOne = beanOne; } public void setBeanTwo(YetAnotherBean beanTwo) { this.beanTwo = beanTwo; } public void setIntegerProperty(int i) { this.i = i; } }
3.2 构造器注入例子
<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 { 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; } }
3.3 采用static方法返回对象实例
<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; } }
4. 构造器注入还是Setter注入?
提倡使用setter注入。BeanFactory对于它所管理的bean提供两种注入依赖方式(实际上它支持同时使用两种注入方式)。需要注入的依赖将保存在BeanDefinition中,它根据所指定的PropertyEditor将属性从一种格式转换成另外一种格式。大部分Spring用户采用XML方式进行定义即可
处理bean依赖关系的步骤
1. 根据定义bean的配置创建并初始化BeanFactory实例
2. 每个bean的依赖将以属性、构造器参数、静态工厂方法参数的形式出现。当这些bean被实际创建时,这些依赖将会提供给bean。
3. 每个属性或构造器参数既可以是一个实际的值,也可以是对该容器中另一个bean的引用
4. 每个指定的属性或构造器参数值必须能够被转换成特定的格式或构造参数所需的类型。默认情况下,Spring会以String类型提供值转换成各种内置类型,比如int、long、String、boolean等。
Spring会在容器被创建时验证容器中每个bean的配置,包括验证那些bean所引用的属性是否指向一个有效的bean。然而,在bean被实际创建之前,bean的属性并不会被设置。对于那些singletion类型和被设置为提前实例化的bean(比如ApplicationContext中的singletion bean)而言,bean实例将与容器同时被创建。而另一些bean会在需要时候被创建,其依赖的bean也被创建和分配。
默认情况下ApplicationContext实现中的bean采用提前实例化的singletion模式!