事务失效为哪般?

这一生的挚爱 提交于 2020-01-07 11:53:37

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

       最近生产环境发现一个很奇怪的问题,之前用的好好的Spring事务配置在一个接口上突然失效了,其余接口正常。原因究竟是什么呢?且听我慢慢道来。:-)

问题描述:

注:问题的描述是在demo工程中对原问题的模拟,只是为了说明问题,所以数据看起来有点随意,请勿见怪。

数据库表userinfo中有两条数据

clip_image002

配置Sping事务并对两条记录进行同时删除,此时由于两条delete中间有一个异常抛出,所以两条记录不会被删除,一切到这还是非常合乎常理的。

clip_image004

clip_image006

走读问题代码发现工程中有一个类实现了BeanFactoryPostProcessor接口,并且在postProcessBeanFactory方法中对上面调用的接口调用了getBeansOfType,于是在demo中进行模拟,类似于下面这样:

此时,我们在demo工程配置MyBeanFactoryPostProcessor对应的bean,重新调用接口中的delete方法,从结果可以看出,方法中的两个delete操作已经不在同一事务中了,也就是说Spring事务失效了!

clip_image010

问题分析:

MyBeanFactoryPostProcessor的bean存在前,可以看到对应的事务配置生效,并生成了代理类。

clip_image012

而配置MyBeanFactoryPostProcessor之后,没有事务的代理类生成了,当然事务也就会失效。

那么为什么新加一个实现了BeanFactoryPostProcessor接口的类就会有这个影响呢?

clip_image014

如上图所示,spring的bean初始化过程中,会在图中的1)处调用实现了BeanFactoryPostProcessor的类中的postProcessBeanFactory方法对beanFactory进行后处理

然后执行到图中的2)处调用BeanPostProcessor的方法拦截bean的创建过程,做一些前置后置处理,spring的aop生成代理类(如本文中的事务切面)就是在这里完成的

MyBeanFactoryPostProcessor实现了BeanFactoryPostProcessor接口,并在postProcessBeanFactory中调用getBeansOfType完成了对userDao的实例化,执行到2)时

也就不能生成对应的代理类,从而导致了事务配置的实效。上面的分析也可以从spring的启动日志中得到验证:

clip_image016

当MyBeanFactoryPostProcessor存在时,在internalAutoProxyCreator之前,userDao的bean已经完成了实例化。

clip_image018

而没有MyBeanFactoryPostProcessor的情况下,userDao是可以生成事务代理类的。

注:AspectJAwareAdvisorAutoProxyCreator实现了BeanPostProcessor接口

最后我们也可以从类的注释说明看出spring是不建议通过实现BeanFactoryPostProcessor来与bean的实例化进行交互的。

测试工程:https://git.oschina.net/zjg23/SpringTransactionTest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!