作者:kaiping2011 | 来源:互联网 | 2024-12-18 09:47
本文探讨了一个特定于Spring4.2.5的问题,即在应用上下文刷新事件(ContextRefreshedEvent)触发时,带有@Transactional注解的Bean未能正确代理事务。该问题在Spring4.1.9版本中正常运行,但在升级至4.2.5后出现异常。
在 Spring 4.2.5 中遇到一个问题,当应用上下文刷新事件(ContextRefreshedEvent)被触发时,带有 @Transactional
注解的 Bean 未能正确代理事务。具体来说,SettingService
Bean 虽然标注了事务注解,但其在事件处理过程中并未如预期那样作为 JDK 动态代理实例存在。
以下是相关代码示例:
public class DefaultConfigManager implements ApplicationListener, ConfigManager {
@Autowired
private SettingService service;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("Proxy: " + AopUtils.isJdkDynamicProxy(service));
String key = service.getSystemSetting("KEY");
}
}
在 Spring 4.1.9 版本中,上述代码能够正常运行,控制台输出显示 SettingService
Bean 是一个动态代理对象,表明事务管理功能正常运作。然而,在升级到 Spring 4.2.5 后,相同的代码开始抛出异常:
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:993)
进一步检查发现,此时 SettingService
Bean 已不再是一个代理对象,这意味着事务管理功能失效。
尽管按照 Spring 文档说明,所有 Bean 和后处理器应在发布 ContextRefreshedEvent
之前完成初始化,但实际情况似乎并非如此。已确认应用程序上下文中配置了 Hibernate 事务管理器,且 tx:annotation-driven
元素已设置,@Transactional
注解应用于实现类而非接口,同时系统中不存在循环依赖。使用的 Hibernate 版本为 4.2.20.Final。
此问题可能与 Spring 4.1 和 4.2 版本之间的一些已知差异有关。例如,Spring 4.2 引入了一些针对 AOP 代理机制的改进,这些改进可能导致了旧有代码行为的变化。此外,Spring 4.2 对事务管理器的配置方式进行了调整,可能影响了事务代理的创建过程。
解决这一问题的一种方法是在类级别而非方法级别添加 @Transactional
注解。通过这种方式,可以确保整个类的所有公共方法都处于事务管理之下,从而避免因特定方法调用而引发的事务管理问题。