【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
最近生产环境发现一个很奇怪的问题,之前用的好好的Spring事务配置在一个接口上突然失效了,其余接口正常。原因究竟是什么呢?且听我慢慢道来。:-)
问题描述:
注:问题的描述是在demo工程中对原问题的模拟,只是为了说明问题,所以数据看起来有点随意,请勿见怪。
数据库表userinfo中有两条数据
配置Sping事务并对两条记录进行同时删除,此时由于两条delete中间有一个异常抛出,所以两条记录不会被删除,一切到这还是非常合乎常理的。
走读问题代码发现工程中有一个类实现了BeanFactoryPostProcessor接口,并且在postProcessBeanFactory方法中对上面调用的接口调用了getBeansOfType,于是在demo中进行模拟,类似于下面这样:

此时,我们在demo工程配置MyBeanFactoryPostProcessor对应的bean,重新调用接口中的delete方法,从结果可以看出,方法中的两个delete操作已经不在同一事务中了,也就是说Spring事务失效了!
问题分析:
MyBeanFactoryPostProcessor的bean存在前,可以看到对应的事务配置生效,并生成了代理类。
而配置MyBeanFactoryPostProcessor之后,没有事务的代理类生成了,当然事务也就会失效。

那么为什么新加一个实现了BeanFactoryPostProcessor接口的类就会有这个影响呢?
如上图所示,spring的bean初始化过程中,会在图中的1)处调用实现了BeanFactoryPostProcessor的类中的postProcessBeanFactory方法对beanFactory进行后处理
然后执行到图中的2)处调用BeanPostProcessor的方法拦截bean的创建过程,做一些前置后置处理,spring的aop生成代理类(如本文中的事务切面)就是在这里完成的
MyBeanFactoryPostProcessor实现了BeanFactoryPostProcessor接口,并在postProcessBeanFactory中调用getBeansOfType完成了对userDao的实例化,执行到2)时
也就不能生成对应的代理类,从而导致了事务配置的实效。上面的分析也可以从spring的启动日志中得到验证:
当MyBeanFactoryPostProcessor存在时,在internalAutoProxyCreator之前,userDao的bean已经完成了实例化。
而没有MyBeanFactoryPostProcessor的情况下,userDao是可以生成事务代理类的。
注:AspectJAwareAdvisorAutoProxyCreator实现了BeanPostProcessor接口
最后我们也可以从类的注释说明看出spring是不建议通过实现BeanFactoryPostProcessor来与bean的实例化进行交互的。

测试工程:https://git.oschina.net/zjg23/SpringTransactionTest
来源:oschina
链接:https://my.oschina.net/u/999023/blog/689593







