SpringBoot启动源码解读(13)

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方法。

你可能感兴趣的:(SpringBoot启动源码解读(13))