构造函数注入:
Set注入法的缺点是,它无法清晰的表示出哪些属性是必须的,哪些是可选的。而构造函数注入法的优势是通过构造函数来强制依赖关系。
使用Set注入时,我们通过<property>元素来注入属性的值。构造函数注入也一样,只不过是通过<bean>元素下的<constructor-arg>元素来指定实例化这个bean的时候需要传递的参数。constructor-arg没有name属性。
解决构造函数参数的不确定性:
有2种方法可以用来处理构造函数的不确定性:通过序号和类型。<constructor-arg>元素有一个可选的index属性,可以用它来指定构造函数的顺序。
<bean id="foo" class="com.springinaction.Foo">
<constructor-arg index="1">
<value>http://www.manning.com</value>
</constructor>
<constructor-arg index="0">
<value>http://www.springinaction.com</value>
</constructor>
</bean>
另一种方法是使用type属性。可以通过type属性确定参数的类型
<bean id="foo" class="com.springinaction.Foo">
<constructor-arg type="java.lang.String">
<value>http://www.manning.com</value>
</constructor>
<constructor-arg type="java.net.URL">
<value>http://www.springinaction.com</value>
</constructor>
</bean>
使用构造函数注入的理由:
1、构造函数注入强制使用依赖契约。就是如果没有提供所有需要的依赖,一个Bean就无法被实例化。
2、由于Bean的依赖都通过它的构造函数设置了,所以没有必要再写多余的Set方法。
3、因为只能通过构造函数设置类的属性,这样你有效的保证了属性的不可变性。
Set注入的依据:
1、如果Bean有很多依赖,那么构造函数的参数列表会很长。
2、构造函数只能通过参数的个数和类型来区分。
3、如果构造函数的参数中有2个以上是相同类型的,那么很难确定每个参数的用途。
4、构造函数注入不利于自身的继承。
自动装配:
你可以让Spring自动装配,只要设置需要自动装配的<bean>中的autowire属性。
<bean id="foo" class="com.springinaction.Foo" autowire="autowire type"/>
byName-视图在容器中寻找和需要自动装配的属性名相同的Bean.
byType-视图在容器中寻找一个与需要自动配置的属性类型相同的Bean.
constructor-视图在容器中查找与需要自动装配的Bean的构造参数一致的一个或多个Bean.
autodetect-首先尝试使用congstructor来自动装配,然后使用byType方式。
使用Spring的特殊Bean
编写一个后处理Bean,Spring为你提供了2次机会,让你切入到Bean的生命周期中,检查或者修改它的配置,这叫做后处理,后处理实在Bean实例化以及装配完成之后发生的。postProcessBeforeInitialization()方法在Bean初始化之前被调用。postProcessAfterInitialization()方法在初始化之后马上被调用。
package com.wyq.hibernate;
import java.lang.reflect.Field;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class Fuddifier implements BeanPostProcessor {
/**
* postProcessAfterInitialization()方法循环Bean的所有属性,寻找java.lang.String类型的属性。对于每个String属性,把它传递给
* fuddify()方法,这个方法将String将变成唠叨用语。
*/
public Object postProcessAfterInitialization(Object bean, String name)
throws BeansException {
Field[] fields = bean.getClass().getDeclaredFields();
try{
for(int i=0;i<fields.length;i++){
if(fields[i].getType().equals(java.lang.String.class)){
fields[i].setAccessible(true);
String original = (String)fields[i].get(bean);
fields[i].set(bean,fuddify(original));
}
}
}catch(IllegalAccessException e){
e.printStackTrace();
}
return bean;
}
/**
* postProcessBeforeInitialization()方法没有做任何有意义的工作,它只是简单的返回没有修改过的Bean.
*/
public Object postProcessBeforeInitialization(Object bean, String name)
throws BeansException {
return bean;
}
private String fuddify(String orig){
if(orig==null)return orig;
return orig.replaceAll("(r|l)", "w").replaceAll("(R|L)", "W");
}
}
注册后处理Bean:如果你的应用系统运行在Bean工厂中,你需要调用工厂的addBeanPostProcessor()方法来注册BeanPostProcessor.
BeanPostProcessor fuddifier = new Fuddifier();
factory.addBeanPostProcessor(fuddifier);
如果你是使用应用上下文,你只需要像注册其他Bean那样注册后处理Bean.
posted on 2009-10-29 14:59
王永庆 阅读(245)
评论(0) 编辑 收藏 所属分类:
SPRING