初衷
日常开发中经常用到@Transaction注解,那你知道它是怎么应用到你的业务代码中的吗?本篇文章将从以下两个方面阐述Spring事务实现原理:
解析并加载事务配置:本质上是解析xml文件将标签加载成 BeanDefinition 对象;
生成事务代理对象并运行:本质上是Spring AOP在事务这块的应用,将业务Bean替换成事务代理对象(JdkDynamicAopProxy:JDK代理,CglibAopProxy:CGLIB代理);
本文使用的源码版本是Spring 4.3.18.RELEASE,使用的是XML开启事务。
关键类
这里列出几个核心类,提前留个印象,后面会讲解什么时候调用
XmlBeanDefinitionReader 加载XML定义的Bean入口
TxNamespaceHandler 解析XML中的事务标签:advice、annotation-driven等;
InfrastructureAdvisorAutoProxyCreator 该类实现了 BeanPostProcessor 接口(可以在Bean初始化后进行替换),是生成事务代理类并替换的关键类;
AnnotationTransactionAttributeSource 用来解析业务方法使用注解 @Transaction 上的配置,提供给 TransactionInterceptor 使用;
TransactionInterceptor 事务拦截类:真正处理事务的类,开启、回滚事务,可以理解成切面中的通知:做什么;
BeanFactoryTransactionAttributeSourceAdvisor 实现了Advisor接口,可以理解为切面:切点(TransactionAttributeSourcePointcut) + 通知(TransactionInterceptor)。
示例代码:
1. 解析并加载事务配置
加载的入口(同时也是Spring容器加载的核心代码):
事务配置的解析在上面的obtainFreshBeanFactory,由于我们使用的是ClassPathXmlApplicationContext 作为容器,它的解析类为:XmlBeanDefinitionReader;核心方法:
TxNamespaceHandler 最终交给类 AnnotationDrivenBeanDefinitionParser 进行解析事务配置;
到这里,事务配置的加载就结束了,上面的步骤只是将事务的关键类变成 BeanDefinition,实际上还没有生成Bean对象的,下面我们看下BeanDefinition 是如何变成Bean的(这一个步骤不是Spring事务独有的,是所有BeanDefinition 的共同逻辑),然后是如何生成业务bean代理对象并替换业务bean的。
2. 生成事务代理对象
入口在1.解析并加载事务配置列举的finishBeanFactoryInitialization(beanFactory) 方法中:
beanFactory.preInstantiateSingletons() 具体方法如下:
getBean(beanName) 方法比较复杂,这里只列举出关键点:AbstractAutowireCapableBeanFactory 的 initializeBean方法,所有bean的创建都绕不开这个方法,这个方法是执行实现了 BeanPostProcessor 的bean的逻辑:
InfrastructureAdvisorAutoProxyCreator 的 postProcessAfterInitialization 定义在父类:AbstractAutoProxyCreator,AbstractAutoProxyCreator这个类同时是Spring AOP处理的入口,并不是说事务处理独有的,具体实现如下:
proxyFactory.getProxy(getProxyClassLoader()) 方法实现:
通过2. 生成事务代理对象,此时创建的bean就是以及被JDK或者CGLIB代理的类,这一步是Spring AOP通用的处理逻辑,那具体是怎么运行的呢?
JDK动态代理运行:
CGLIB代理运行:
事务的最终执行类 TransactionInterceptor 的invoke 方法:
总结
以上就是事务应用到业务场景中的原理,可以简单理解:Spring事务是在Spring AOP的基础上开发的,关注关键类:TransactionInterceptor 的实现就行了,不管是JDK动态代理还是CGLIB代理都是要用到这个类去提交/回滚事务的。如有错误欢迎指出。
领取专属 10元无门槛券
私享最新 技术干货