最近生产环境发现一个很奇怪的问题,以前用的好好的Spring事务配置在一个接口上忽然失效了,其他接口正常。缘由到底是什么呢?且听我慢慢道来。:-)git
问题描述:spring
注:问题的描述是在demo工程中对原问题的模拟,只是为了说明问题,因此数据看起来有点随意,请勿见怪。数据库
数据库表userinfo中有两条数据post
配置Sping事务并对两条记录进行同时删除,此时因为两条delete中间有一个异常抛出,因此两条记录不会被删除,一切到这仍是很是合乎常理的。测试
走读问题代码发现工程中有一个类实现了BeanFactoryPostProcessor接口,而且在postProcessBeanFactory方法中对上面调用的接口调用了getBeansOfType,因而在demo中进行模拟,相似于下面这样:.net
此时,咱们在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