美文网首页
声明式事务源码分析之EnableTransactionManag

声明式事务源码分析之EnableTransactionManag

作者: 会上树的程序猿 | 来源:发表于2020-06-03 10:50 被阅读0次

    上节我们通过简单的案例来熟悉了spring注解版的声明式事务的开发,其实大家可以分别测一下,当我们不配置事务管理以及不贴注解EnableTransactionManagement时我们执行逻辑时是否会插入记录到数据库中,答案不行的,注解EnableTransactionManagement的主要目的是开启事务的功能,接下来的学习我们来围绕它进行

    EnableTransactionManagement

    点进去之后发现此注解位于org.springframework.transaction.annotation包下,具体代码片段如下:

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({TransactionManagementConfigurationSelector.class})
    public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;
    
    AdviceMode mode() default AdviceMode.PROXY;
    
    int order() default 2147483647;
    

    }

    看到上述的代码我相信大家都不陌生,spring 的注解开发的套路,还是给我们的容器中导入一个组件【TransactionManagementConfigurationSelector】,接下来的核心就是它了

    TransactionManagementConfigurationSelector

    简单的说这个组件的作用是作为一个事务配置管理的选择器来出现帮助我们都做了什么事,方法进去我们发下如下的代码片段:

     protected String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        case PROXY:
            return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
        case ASPECTJ:
            return new String[]{this.determineTransactionAspectClass()};
        default:
            return null;
        }
    }
    

    其中通过传入的参数判断你到底是那种类型的,并为我们导入其对应的组件,我们这里是PROXY此类型的,为啥这么肯定了,在我们的EnableTransactionManagement 注解类中默认的就是它,大家可以在开头的代码片段中看到,是PROXY类型,这里帮我们导入的是AutoProxyRegistrar和ProxyTransactionManagementConfiguration这两个组件,分别来看:

    AutoProxyRegistrar

    该类实现了ImportBeanDefinitionRegistrar接口,也就是说其主要的作用是帮我们给容器注册其组件,接下来我们通过方法#registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 来看帮我们注册的具体是那个组件

    • 1.首先通过如下的代码操作获取当前的当前容器的类型【AdviceMode:属于JDK的代理】
    Object mode = candidate.get("mode");
    

    前面我们已经知道了是PROXY类型的,所以接着看如下的代码片段:

     Object proxyTargetClass = candidate.get("proxyTargetClass");
    
     if (mode == AdviceMode.PROXY) {
                        AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                        if ((Boolean)proxyTargetClass) {
                            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                            return;
                        }
                    }
    

    这里有两个判断,来看下:

    • 如果当前获取到了有proxyTargetClass【代理目标对象】时,会去执行方法AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry),很显然我们这里是不会调用的,在我们的注解类EnableTransactionManagement中proxyTargetClass的获取默认就是false,代码如下:
     boolean proxyTargetClass() default false;
    

    所以我们直接来分析方法AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

      @Nullable
      public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
        return registerAutoProxyCreatorIfNecessary(registry, (Object)null);
    }
    
    @Nullable
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
        return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
    }
    

    从上面的代码我们可以看到的是AutoProxyRegistrar帮我们想容器注册了一个InfrastructureAdvisorAutoProxyCreator【基础的自动代理增强创建器】,看到这个是不是跟我们Aop中【AspectJAwareAdvisorAutoProxyCreator】这个有点相似,其实质是一样的,只不过是事务中帮我们注册的是InfrastructureAdvisorAutoProxyCreator此类型的,我们看看它的作用:

    InfrastructureAdvisorAutoProxyCreator

    该类位于org.springframework.aop.framework.autoproxy包下,其继承实现关系如下图所示:

    InfrastructureAdvisorAutoProxyCreator.png

    不难发现InfrastructureAdvisorAutoProxyCreator实质也是一个【InstantiationAwareBeanPostProcessor】类型的后置处理器,那作为后置处理器的话,我们已经清楚的知道了它的作用:

    • 帮助我们完成对象的创建

    • 将创建完成的对象进行包装------> 返回其对应的代理对象

    • 获取拦截器链并进行相应的转化为一个个的拦截器

    • 利用拦截器机制进行链式的执行我们的目标方法

    下面的代码是具体的注册过程:

       @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
            BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
    
            return null;
        } else {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", -2147483648);
            beanDefinition.setRole(2);
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
            return beanDefinition;
        }
    }
    

    上述就是AutoProxyRegistrar组件帮我们所做的事,接下来我们来看看另外一个组件

    ProxyTransactionManagementConfiguration

    该类位于org.springframework.transaction.annotation包下,其实质也是一个配置类,该容器注册一些组件,这些组件有 transactionAdvisor 【事务增强器】和transactionInterceptor【事务拦截器】 ,具体注册的逻辑代码如下:

    • transactionAdvisor 【事务增强器】
      @Bean(
        name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
    )
    @Role(2)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        advisor.setAdvice(transactionInterceptor);
        if (this.enableTx != null) {
            advisor.setOrder((Integer)this.enableTx.getNumber("order"));
        }
    
        return advisor;
    }
    
    • transactionInterceptor【事务拦截器】
    @Bean
    @Role(2)
    public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource);
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }
    
        return interceptor;
    }
    

    其中在注册组件的过程中我们发现会有这样一个属性TransactionAttributeSource【事务属性源】,同样也是注册进来的

     @Bean
    @Role(2)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }
    

    进去方法来到AnnotationTransactionAttributeSource类【事务注解的属性】,其中方法#AnnotationTransactionAttributeSource(boolean publicMethodsOnly)需要我们注意一点

    public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
        this.publicMethodsOnly = publicMethodsOnly;
        if (!jta12Present && !ejb3Present) {
            this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
        } else {
            this.annotationParsers = new LinkedHashSet(4);
            this.annotationParsers.add(new SpringTransactionAnnotationParser());
            if (jta12Present) {
                this.annotationParsers.add(new JtaTransactionAnnotationParser());
            }
    
            if (ejb3Present) {
                this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
            }
        }
    
    }
    

    方法主要是当前是那种类型的事务并进行解释其对应的事务注解信息,当然这里用的是spring的自己的事务,也就是如下代码:

     if (!jta12Present && !ejb3Present) {
            this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
        } else {
            this.annotationParsers = new LinkedHashSet(4);
            this.annotationParsers.add(new SpringTransactionAnnotationParser());
    

    接着我们看到是通过SpringTransactionAnnotationParser【事务注解解析器】来帮助我们解析具体的注解信息,进去来到类SpringTransactionAnnotationParser#parseTransactionAnnotation(AnnotationAttributes attributes)方法来完成事务注解的解析过程,解析之前还是有一步重要的动作来看方法

    @Override
    @Nullable
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                element, Transactional.class, false, false);
        if (attributes != null) {
            return parseTransactionAnnotation(attributes);
        }
        else {
            return null;
        }
    }
    

    这段代码很简单,无非就是先拿到我们的注解类Transactional【事务注解】然后封装成一个注解属性【AnnotationAttributes 】,接着调用我们的具体解析方法,Transactional具体都有哪些属性我们来看看:

    public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";
    
    @AliasFor("value")
    String transactionManager() default "";
    
    Propagation propagation() default Propagation.REQUIRED;
    
    Isolation isolation() default Isolation.DEFAULT;
    
    int timeout() default -1;
    
    boolean readOnly() default false;
    
    Class<? extends Throwable>[] rollbackFor() default {};
    
    String[] rollbackForClassName() default {};
    
    Class<? extends Throwable>[] noRollbackFor() default {};
    
    String[] noRollbackForClassName() default {};
    

    }

    上述的这些属性我们都是可以配置的如:

    @Service
    public class UserService {
    
    @Resource
    private UserDao userDao;
    @Transactional(propagation = Propagation.REQUIRED ,isolation = Isolation.DEFAULT,timeout = 1)
    public void insert(){
        userDao.insert();
        System.out.println("插入成功....");
    
        int i = 10 / 0;
    }
    

    感兴趣的可以自己玩玩,既然我们已经到AnnotationTransactionAttributeSource的作用,回到我们分析的入口类ProxyTransactionManagementConfiguration

    • 我们在方法#transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor)中

    • 给容器中注册了一个BeanFactoryTransactionAttributeSourceAdvisor【事务增强器】

    • 接着事务增强器保存我们前面分析的事务注解信息

    • 保存事务拦截器到事务增强器中

    • 最后进行排序操作

    期间我们用到了事务拦截器,那么我们来看看这事务拦截器的作用

    TransactionInterceptor

    该类位于org.springframework.transaction.interceptor包下,发下该类实现了MethodInterceptor接口,代码片段如下:

    public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
    public TransactionInterceptor() {
    }
    

    还记得我们在Aop目标方法分析时,有一步就是将每一个拦截器包装成一个MethodInterceptor类型的拦截器,其实看到这里我们的事务拦截器的跟Aop的原理是类似的,接着回到我们的TransactionInterceptor类中#invoke(MethodInvocation invocation)方法

     @Nullable
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
        Method var10001 = invocation.getMethod();
        invocation.getClass();
        return this.invokeWithinTransaction(var10001, targetClass, invocation::proceed);
    }
    

    其中方法#invokeWithinTransaction(....)执行目标类的,进去我们来到l类TransactionAspectSupport中的#invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation)方法,具体看看方法做了哪些处理:

    • 首先获取事务注解属性
     TransactionAttributeSource tas = this.getTransactionAttributeSource();
        TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
    

    上述只是做铺垫,接下来我们来看重头戏,是如何获取我们的事务管理器的,代码片段如下:

    TransactionManager tm = this.determineTransactionManager(txAttr);
    

    继续跟踪代码来到方法#determineTransactionManager(@Nullable TransactionAttribute txAttr)

     @Nullable
    protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
        if (txAttr != null && this.beanFactory != null) {
            String qualifier = txAttr.getQualifier();
            if (StringUtils.hasText(qualifier)) {
                return this.determineQualifiedTransactionManager(this.beanFactory, qualifier);
            } else if (StringUtils.hasText(this.transactionManagerBeanName)) {
                return this.determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
            } else {
                TransactionManager defaultTransactionManager = this.getTransactionManager();
                if (defaultTransactionManager == null) {
                    defaultTransactionManager = (TransactionManager)this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
                    if (defaultTransactionManager == null) {
                        defaultTransactionManager = (TransactionManager)this.beanFactory.getBean(TransactionManager.class);
                        this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
                    }
                }
    
                return defaultTransactionManager;
            }
        } else {
            return this.getTransactionManager();
        }
    }
    

    上述代码主要的操作是通过不同的方式去获取我们的事务管理器实例,分别来看:

    • 1.通过注解 @Qualifier去获取
     String qualifier = txAttr.getQualifier();
            if (StringUtils.hasText(qualifier)) {
                return this.determineQualifiedTransactionManager(this.beanFactory, qualifier);
    

    方法进去来到具体是如何实现的过程:

    private PlatformTransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {
        PlatformTransactionManager txManager = asPlatformTransactionManager(this.transactionManagerCache.get(qualifier));
        if (txManager == null) {
            txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
                    beanFactory, PlatformTransactionManager.class, qualifier);
            this.transactionManagerCache.putIfAbsent(qualifier, txManager);
        }
        return txManager;
    }
    
    • 方式二:通过bean的名字去获取
      else {
                TransactionManager defaultTransactionManager = this.getTransactionManager();
                if (defaultTransactionManager == null) {
                    defaultTransactionManager = (TransactionManager)this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
                    if (defaultTransactionManager == null) {
                        defaultTransactionManager = (TransactionManager)this.beanFactory.getBean(TransactionManager.class);
                        this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
                    }
                }
    

    很显然我们是自己配置的事务管理器,所以是通过方式二的去获取事务管理器的,既然我们了解了事务管理器的获取过程,回到我们的方法#invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation)接着看:

    • 接着获取我们的PlatformTransactionManager
    PlatformTransactionManager ptm = this.asPlatformTransactionManager(tm);
    

    前提是之前没有添加指定任何transactionmanger最终会从容器中按照类型获取一个PlatformTransactionManager

    • 最后执行我们的目标方法
      1. 如果是正常的情况下直接提交事务
     private Mono<Void> commitTransactionAfterReturning(@Nullable TransactionAspectSupport.ReactiveTransactionInfo txInfo) {
            if (txInfo != null && txInfo.getReactiveTransaction() != null) {
                if (TransactionAspectSupport.this.logger.isTraceEnabled()) {
                    TransactionAspectSupport.this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
                }
    
                return txInfo.getTransactionManager().commit(txInfo.getReactiveTransaction());
            } else {
                return Mono.empty();
            }
        }
    

    2.如果有异常的话,进行事务回滚

    private Mono<Void> completeTransactionAfterThrowing(@Nullable TransactionAspectSupport.ReactiveTransactionInfo txInfo, Throwable ex) {
            if (txInfo != null && txInfo.getReactiveTransaction() != null) {
                if (TransactionAspectSupport.this.logger.isTraceEnabled()) {
                    TransactionAspectSupport.this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
                }
    
                return txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex) ? txInfo.getTransactionManager().rollback(txInfo.getReactiveTransaction()).onErrorMap((ex2) -> {
                    TransactionAspectSupport.this.logger.error("Application exception overridden by rollback exception", ex);
                    if (ex2 instanceof TransactionSystemException) {
                        ((TransactionSystemException)ex2).initApplicationException(ex);
                    }
    
                    return ex2;
                }) : txInfo.getTransactionManager().commit(txInfo.getReactiveTransaction()).onErrorMap((ex2) -> {
                    TransactionAspectSupport.this.logger.error("Application exception overridden by commit exception", ex);
                    if (ex2 instanceof TransactionSystemException) {
                        ((TransactionSystemException)ex2).initApplicationException(ex);
                    }
    
                    return ex2;
                });
            } else {
                return Mono.empty();
            }
        }
    

    可以发现的是,不管是事务提交还是回滚操作,都是通过我们的事务管理器来完成,到这里我们的声明式事务的相关源码分析已完成

    相关文章

      网友评论

          本文标题:声明式事务源码分析之EnableTransactionManag

          本文链接:https://www.haomeiwen.com/subject/afbhzhtx.html