我有一个Spring / Struts2问题,我在Spring论坛上问过但没有回复@Resource no injected sometimes
为了便于阅读,我将在这里重复这个问题。希望它不被认为是垃圾邮件
当我使用@Resource注入bean时,我有一个非常奇怪的问题。我正在使用Struts2 2.2.3.1和Spring 3.0.0提供的Spring插件。 (我无法在不知道正确原因的情况下升级到最新版本的Spring,因为所有程序都在生产中)
问题或观察到的问题是当创建Struts2 Action时,使用@Resource注释的字段应该具有Spring注入的资源。但是,有时候,有时只有一个带注释的资源没有注入,或者值只是null,因此会导致NullPointerException。问题发生的点是未确定的,这意味着在不同环境中运行的同一组程序将导致不同的行为。此外,未注入的资源并不总是相同的。例如,如果存在动作A,B,C以及环境E1和E2,则在E1中A动作有时可能会出现此问题,而在E2中可能是动作B出现问题。有一件事是肯定的,如果在E2 B遇到问题,它会不时发生,A和C不会有问题,或者至少在A和C上没有观察到问题。而且,如果A有5个@Resource字段,当问题发生时,NPE可能在访问第一个资源时被抛出,但下一次可能是第二个资源。
这就是我的意思,问题只发生在“有时”。假设A遇到这种问题,我启动Web服务器(tomcat或WAS),如果问题发生,我第一次访问A,它将在整个服务器启动期间发生。如果在第一次访问A时没有出现问题,那么在整个服务器启动期间,问题就不会发生。此外,如果这次是未注入的第一个资源,那么这个启动将是相同的。
这是我的一些应用程序设置:我使用XML与注释扫描混合。基本上所有的Action,Service,Dao类都是用XML定义的,但Spring的所有属性定义都没有用来扫描实际的类。
样本定义:
码:
<!-- have this in all XML files -->
<context:annotation-config/>
<!-- an action definition, all actions are scoped prototype. It will use adm.common.admBranchesManager in the action with field annotated with @Resource -->
<bean id="adm.common.chooseBranchAction" class="com.bi.wms.adm.common.web.ChooseBranchAction" scope="prototype"></bean>
<!-- all service and dao are singleton and do not have any problem, all service/Manager are annotated with @Transactional. In Action we only code against interface and not actual concrete class -->
<bean id="adm.common.admBranchesManager" class="com.bi.wms.adm.common.service.impl.AdmBranchesManagerImpl"/>
<bean id="adm.common.admBranchesDao" class="com.bi.wms.adm.common.dao.jdbc.AdmBranchesDaoImpl"/>
此外,对于所有操作,它们都扩展了一个抽象操作,该操作具有会话范围的资源字段。
码:
<bean id="base.wms.login" class="com.bi.wms.common.model.WmsLogin" destroy-method="logout" scope="session">
<aop:scoped-proxy />
<property name="admUserSessionsManager" ref="adm.operation.admUserSessionsManager"/>
</bean>
以下是示例操作的一部分:代码:
//this class is just a sample not the actually one thats having the problem, AbstractWmsAction is the class that have a session-scoped bean
public class AdmWmsControlAction extends AbstractWmsAction
{
@Resource(name = "adm.operation.admWmsBatchGroupsManager")
private AdmWmsBatchGroupsManager admWmsBatchGroupsManager;
@Resource(name = "adm.operation.admWmsControlManager")
private AdmWmsControlManager admWmsControlManager;
//sometimes we use setters for injecting but that doesnt stop the problem from happening
//....omit
}
不知道是否有人有此类问题。如果需要其他信息,我会尽力提供。
谢谢
我之前在使用注释时遇到过类似的问题。这就是为什么我更喜欢在有限的情况下使用@Transactional。哪些类使用@Transactional注释?实现还是界面?
我只是通过调试器快速查看了这个,但我认为你最终可能会遇到多个bean,一个使用@Transactional-ly注释类创建的Spring代理,另一个在应用程序上下文中定义。我建议如果你在Spring配置文件中定义服务,你也可以在那里定义事务代理,并使用@Resource注释按名称注入代理,或者删除xml中的配置,并按类型注入你的注释。这样,如果您有无法解析的类型重复匹配,Spring会通知您。
在这段时间之后做一个笔记,我还没有找到真正的原因和解决方案。
但是,时间已经证明升级到Spring 2.3.3或更高版本可以解决问题,或者至少问题还没有出现