• Spring事务:@Transactional注解的一些记录


    1,原理

    Spring通过代理实现事务管理;

    Java中代理分为静态代理和动态代理两种;

    静态代理主要是aspectJ,在编译阶段将增强代码加入到字节码中;

    动态代理有jdk动态代理和cglib两种;

    Jdk动态代理是在运行过程中生成被代理类的子类,并将增强代码加入到方法中;

    Cglib动态代理是在运行过程中实现被代理接口的实例,并将增强代码加入到方法中;

    Spring采用的是动态代理而不是静态代理;

     

    实际的事务方法注册流程:

    容器启动时,创建bean;在AbstractBeanFactory的createBean方法中,会调用resolveBeforeInstantiation[Bean处理器],看是否需要产生代理对象;

    resolveBeforeInstantiation中,调用applyBeanPostProcessorsAfterInitialization方法处理,会循环调用所有bean的后置处理器的postProcessAfterInitialization方法;

    处理事务注解的后置处理器是AbstractAdvisingBeanPostProcessor,在该类的postProcessAfterInitialization中,我们直接看isEligible(bean, beanName)方法,继续调用AopUtils.canApply方法,看是否是由pointcut驱动的advisor,如果是,那么会调用MethodMatcher的matches方法;对于@Transactional注解来说,会由TransactionAttributeSourcePointcut这个实现类来做match的工作,最终会找到AbstractFallbackTransactionAttributeSource这个类中的getTransactionAttribute

    方法来看是否使用到该注解,这里的核心方法是computeTransactionAttribute;

    computeTransactionAttribute逻辑:首先检查该方法是否是public修饰的,然后看该注解是在方法上使用的还是在类上使用的;

     

    2,使用

    在需要事务的方法上或者类上加上@Transacional注解即可;

     

    3,事务失效场景

    首先定义接口 I1,I2;

    定义I1的普通方法I1m1,事务方法I1t1;

    定义I2的普通方法I2m1,事务方法I2t1;

    1)I1m1调用I1t1时,I1m1不属于事务;

    2)I1m1调用I1t1时,如果是直接this调用I1t1,那么I1t1也没有事务,因为spring需要注入接口才能管理事务

    3)I1t1或者I2t1不是public修饰的,那么事务失效;

    4)I1t1调用I2t1,并且try了I2t1的异常;如果I2t1抛异常了,并且I2t1没有catch异常,那么程序会抛出Transaction rolled back because it has been marked as rollback-only

    异常;因为I2t1抛异常时候,spring会将其标记为回滚,然后I1t1提交commit的时候,发现I2t1有异常,所以导致不能正提交事务,随即抛出该异常。

  • 相关阅读:
    C#动态方法调用
    递归查询SQL语句
    Jquery获取下拉选择节点名称值赋给textbox文本框 获取 父节点的栏目名称编号
    C# 获取指定目录下所有文件信息
    引用借以记录借鉴 实现记住密码和自动登录功能
    摘用的一个实现在线发送短信接口功能
    Winform文件夹图片批量压缩整理修改
    安装包部署项目简述
    一道不错的考试题
    利用ItextSharp 生成PDF文档改进版
  • 原文地址:https://www.cnblogs.com/mmh760/p/15415858.html
Copyright © 2020-2023  润新知