在web项目的开发过程中,很多开发人员发现action层如果没有加入注解@Controller ,而该action中有用到@Autowired去创建service,项目仍然可以正常运行,功能一点也不受影响,这是为什么呢?接下来我将从源码级别为大家揭开答案。
其实说白了这些注解只是为了标识该action不需要我们自己管理,而是用ObjectFactory。
ObjectFactory,是xwork中很重要的一个类,是产生action的地方。单独使用xwork的时候,action都是这个类创建的。
struts2包装了ObjectFactory,自成了一个StrutsObjectFactory,他是继承自ObjectFactory的一个类,因此struts2默认产生action的类就不使用xwork的ObjectFactory了,而是使用StrutsObjectFactory。
struts2的插件struts2-spring-plugin-2.1.8.1.jar,又做了一个对象工厂,StrutsSpringObjectFactory,它的父类是xwork的SpringObjectFactory,最原始的父类也是ObjectFactory,我想xwork提供SpringObjectFactory的目的就是让实现这继承这个类,实现spring工厂。
于是struts2中也就是说有3个 对象工厂,
org.apache.struts2.spring.StrutsSpringObjectFactory(struts2的spring插件提供)
org.apache.struts2.impl.StrutsObjectFactory(struts2自带)
com.opensymphony.xwork2.ObjectFactory(xwork自带)。
他们都可以用于产生action。
在xwork中默认使用ObjectFactory,在struts2中默认使用StrutsObjectFactory。使用struts2的spring插件的时候默认使用StrutsSpringObjectFactory,这些都是自动的,其中前两个都是struts2的内容。都是由
<constant name="struts.objectFactory" value="spring" />
来控制,这里的value,就是
<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
在这bean里面定义的是哪个工厂,struts2就用哪个工厂。<引自http://zhangshuwen5251-163-com.iteye.com/blog/1114030>
这里我们只分析存在struts2-spring-plugin的情况:
第一种:@Controller @Namespace都使用,struts.xml中配置有<constant name="struts.objectFactory" value="spring" />
这种情况无疑是交给spring管理,那么项目肯定是正常的。
第二种:只有@Namespace ,而且struts.xml中没有配置<constant name="struts.objectFactory" value="spring" />
这种情况也许大家就会认为项目就不正常了,因为action中有@Autowired注解,用这个注解的对象肯定是null,其实不然,因为struts2-spring-plugin.jar的struts-plugin.xml中有配置<constant name="struts.objectFactory" value="spring" />。看到这里大家肯定会疑惑,即使对象的管理还是由spring管理,但是@Namespace是struts2的,压根就跟spring没有关系,spring是心有余也力不足呀?答案就在SpringObjectFactory类的
buildBean方法
<span style="font-size:14px;">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); <span style="color:#ff6666;">injectApplicationContext(bean);</span> 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); } }</span>也就是说只要有struts2-spring-plugin.jar存在,且我们的struts.xml中没有覆盖struts.objectFactory常量,不管action是由spring创建的还是由struts2创建的,最终都是交由spring管理的,所以action中的@Autowrie注解依然有效