Spring事务的代码:
总体来说,Spring的事务主要是基于 切面AOP实现。在调用方法之前,创建事务,等方法执行完成,提交事务。主要涉及2个注解:@EnableTransactionManagement 和 @Transactional。
1:注解@EnableTransactionManagement里 ,引入TransactionManagementConfigurationSelector,在Spring的启动过程中,会执行 TransactionManagementConfigurationSelector 的 selectImports 方法,会返回AutoProxyRegistrar 和ProxyTransactionManagementConfiguration类。代码如下:
2:在AutoProxyRegistrar类里,会注册InfrastructureAdvisorAutoProxyCreator,该类继承 SmartInstantiationAwareBeanPostProcessor 接口,这个bean后置器处理器在创建bean实例的时候会调用该接口的函数:postProcessAfterInitialization。
3:在配置类ProxyTransactionManagementConfiguration中,会创建实例 PointcutAdvisor 切面观察者接口实例,类名:BeanFactoryTransactionAttributeSourceAdvisor 。会添加属性:TransactionAttributeSource 和 TransactionInterceptor。
4:在bean创建过程中,可能会创建 getEarlyBeanReference 和 postProcessAfterInitialization 方法,这两个方法的的内容差不多,如下:
5:wrapIfNecessary 方法会调用方法 getAdvicesAndAdvisorsForBean,该方法调用findEligibleAdvisors 方法查找当前合适的 Advisor。在 findAdvisorBeans 里会从IOC中查找到 Advisor 类型的bean定义。这个时候会找到第3部分注册的信息。类型为:BeanFactoryTransactionAttributeSourceAdvisor。
6:BeanFactoryTransactionAttributeSourceAdvisor 实例的 pointcut 属性对象的类型是:TransactionAttributeSourcePointcut 。其继承了StaticMethodMatcherPointcut。再上一步获取到定义的 Advisor之后,会调用 AopUtils#findAdvisorsThatCanApply 方法进行匹配过滤。由于 继承了PointcutAdvisor,所以会调用 AopUtils#canApply(Pointcut,Class<?>, boolean) 方法。
7:TransactionAttributeSourcePointcut 的属性classFilter 是 ClassFilter.TRUE 实例,其matches 方法只会返回true。getMethodMatcher 方法获取到的是其本身,所以最终会获取该类所有申明的方法,对每个方法调用 TransactionAttributeSourcePointcut#matches 方法判断是否匹配。如果获取到了TranscationalAttribute对象,则匹配成功。该方法实现如下:
8:matches方法调用getTransactionAttributeSource 方法获取到的是这个类的对象:AnnotationTransactionAttributeSource。然后调用 getTransactionAttribute 方法获取注解 @Transcational。该方法的核心是调用 computeTransactionAttribute 方法。
9:computeTransactionAttribute 方法里,首先会判断方法是不是public,如果不是,则返回null。所有默认情况下,@Transcational注解在非public方法上不生效。代码如下:
9.1:调用方法 determineTransactionAttribute 解析@Transcational 注解,代码如下:
9.2:在parseTransactionAnnotation方法里会解析 @Transcational 的属性,比如propagation,isolation,timeout,rollbackFor等,并生成RuleBasedTransactionAttribute 类型的对象返回。
10:和 @Transcational 匹配成功后,就要创建创建AOP代理对象,代码如下:
11:AbstractAutoProxyCreator#createProxy 方法里,主要是创建proxyFactory对象。其proxyTargetClass 属性值为true,targetSource是当前bean对象。advisors列表里的值是:BeanFactoryTransactionAttributeSourceAdvisor 对象实例。默认情况下,createProxy 使用的是 JdkDynamicAopProxy 类型代理。如果@Transcational所在类没有继承接口,则返回的是ObjenesisCglibAopProxy类型代码。
12:JdkDynamicAopProxy 是利用JDK的反正机制,使用 Proxy.newProxyInstance 创建代理类:代码如下:
13:在 ObjenesisCglibAopProxy 的createProxy方法里,使用了CGLIB的Enhancer来创建代理对象。其中设置的callbacks 是 DynamicAdvisedInterceptor,其继承了接口:MethodInterceptor。代码如下:
14:以JdkDynamicAopProxy为例子看下有注解@Transcational的方法被调用时发生了什么。当方法被调用的时候,首先进入的是 JdkDynamicAopProxy#invoke 方法。在该invoke方法里,比较核心的是调用 AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice 方法 ,而里面调用了DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice。所以调用关系是:JdkDynamicAopProxy#invoke ---> AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice ---> DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice。
15:DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice 方法实际上得到的是 TransactionInterceptor 对象列表(只有)一个实例。
16:得到 TransactionInterceptor 对象后,生成ReflectiveMethodInvocation对象,并调用其process方法。如下:
17:在process 方法里,会调用TransactionInterceptor 的invoke方法。在invoke方法里,调用 invokeWithinTransaction 方法。该方法就会进行事务的操作。说明,该方法里会获取PlatformTransactionManager 接口的实例,各个数据库连接框架均会有实现,比如:JPA,JDBC,MyBatis等都有实现,比如:JtaTransactionManager。在使用事务的时候,这个事务管理器必须配置。
```
protected ObjectinvokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
// 获取注解@Trasactional的配置属性,是RuleBasedTransactionAttribute类型
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
// 获取配置的TransactionManager。如果在@Trasactional注解中指定了名称,则
// 从IOC中获取指定的TransactionManager。不同的数据库持久层框架,其实现的
// TransactionManager不同,所以这个需要配置正确。
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr ==null || !(tminstanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 创建并获取事务。
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal =null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 提交或者回滚事务。这里会判断异常类型,如果类型和@Transactional配置的一致,则回滚,否则事务会提交
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
}
```
18:方法createTransactionIfNecessary里会调用AbstractPlatformTransactionManager#getTransaction 方法获取事务(AbstractPlatformTransactionManager抽象类供各数据库持久层继承)。其主要逻辑是获取该类的数据库连接Connection, 拿到连接后,设置连接的autoCommit 属性为 false。事务内代码执行后,调用 Connection 的 commit 方法。 如果有满足条件的异常,执行rollback方法。