自動裝配即bean之間的依賴關系無需手動配置。
1. 與自動裝配有關的配置
【org.apache.struts2.StrutsConstants類】
Ø // Spring應該如何裝配。有效值:’name’, ’type’, ’auto’ 和’construtctor’。
STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE
Ø // 由STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE選擇的自動裝配策略是否總是受重視的。默認是false,遺留行為即試圖根據情況決定最好的策略。設置為true表示使用STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE設置的自動裝配策略。
STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT
Ø 3(// Spring是否使用它的類緩存
STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE
2. 自動裝配原理
首先根據在Struts.xml中定義Action時指定的class屬性值獲取Action實例
即appContext.getBean(beanName)
n 如果獲取到,則直接返回。此時所使用的自動裝配策略是applicationContext.xml中設置的裝配策略。
applicationContext.xml中beans的默認自動裝配策略是no,所以如果沒有設置<beansdefault-autowire="autodetect">或者bean的autowire="byName",則Action中的屬性比如personManager不會進行自動裝配。
n 如果獲取不到,則調用buildBean(beanClazz, extraContext)。
u 如果struts.objectFactory.spring.autoWire.alwaysRespect為true,此時會根據Struts定義的自動裝配策略(struts.objectFactory.spring.autoWire)進行自動裝配。
u 如果struts.objectFactory.spring.autoWire.alwaysRespect為false,則按constructor方式進行自動裝配。
參考SpringObjectFactory.java源代碼
@Override public Object buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception { Object o = null; try { o = appContext.getBean(beanName); } catch (NoSuchBeanDefinitionException e) { Class beanClazz = getClassInstance(beanName); o = buildBean(beanClazz, extraContext);//使用Struts定義的自動裝配策略 } if (injectInternal) { injectInternalBeans(o); } return o; } |
public Object buildBean(Class clazz, Map<String, Object> extraContext) throws Exception { Object bean; try { // Decide to follow autowire strategy or use the legacy approach which mixes injection strategies if (alwaysRespectAutowireStrategy) { // Leave the creation up to Spring bean = autoWiringFactory.createBean(clazz, autowireStrategy, false); injectApplicationContext(bean); return injectInternalBeans(bean); } else { bean = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false); bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName()); // We don't need to call the init-method since one won't be registered. bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName()); return autoWireBean(bean, autoWiringFactory); } } catch (UnsatisfiedDependencyException e) { if (LOG.isErrorEnabled()) LOG.error("Error building bean", e); // Fall back return autoWireBean(super.buildBean(clazz, extraContext), autoWiringFactory); } } |
所有有兩種配置方式
第一種:參見1集成步驟中的配置
applicationContext.xml(配置beans的自動裝配策略)
struts.xml中action的class屬性值與application-context.xml的bean的id相同。
第二種:
applicationContext.xml(不配置beans的自動裝配策略)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="login" class="com.jeff.action.LoginAction" scope="prototype"> </bean> <bean id="personManager" class="com.jeff.service.PersonManager" scope="prototype"> </bean> ...
</beans> |
struts.xml(struts.xml中action的class屬性值與application-context.xml的bean的id不同,而是設置為Action的類名)
<package name="first" extends="struts-default" > <action name="login1" class="com.jeff.action.LoginAction1"> <result>/loginInfo.jsp</result> </action> </package> |
第二種配置方式,struts.objectFactory.spring.autoWire才有可能起作用。