@Transactional实现原理及失效的三种情况

06-18 1079阅读

@Transactional实现原理

Transactional是spring中定义的事务注解,在方法或类上加该注解开启事务。主要是通过反射获取当前对象的注解信息,利用AOP(代理模式)对编程式事务进行封装实现

@Transactional实现原理及失效的三种情况
(图片来源网络,侵删)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.transaction.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";
    @AliasFor("value")
    String transactionManager() default "";
    String[] label() default {};
    Propagation propagation() default Propagation.REQUIRED;
    Isolation isolation() default Isolation.DEFAULT;
    int timeout() default -1;
    String timeoutString() default "";
    boolean readOnly() default false;
    Class classTarget = pjp.getTarget().getClass();
        // 获取目标对象类型
        Class[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
        // 获取目标对象方法
        Method objMethod = classTarget.getMethod(methodName, par);
        // 获取该方法上的事务注解
        MyAnnotation annotation = objMethod.getDeclaredAnnotation(MyAnnotation.class);
        return annotation;
    }
 
    /**
     * 开启事务
     *
     * @param annotation
     * @return
     */
    private TransactionStatus begin(MyAnnotation annotation) {
        if (annotation == null) {
            return null;
        }
        return transactionUtil.begin();
    }
 
    /**
     * 提交事务
     *
     * @param transactionStatus
     */
    private void commit(TransactionStatus transactionStatus) {
        if (transactionStatus != null) {
            transactionUtil.commit(transactionStatus);
        }
    }
 
    /**
     * 异常通知进行 回滚事务
     */
    @AfterThrowing("execution(* com.sl.service.*.*(..))")
    public void afterThrowing() {
        // 获取当前事务 直接回滚
        if (transactionStatus != null) {
            transactionUtil.rollback(transactionStatus);
        }
    }
}

失效第一种

Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用

@Service
public class TestServiceImpl {
    @Autowired
    TestMapper testMapper;
    
    @Transactional
    void insert(SysUserOrgPo sysUserOrgPo) {
        int re = testMapper.insert(sysUserOrgPo);
        if (re > 0) {
            throw new BaseException("发生异常")
        }
        
        testMapper.insert(new SysUserOrgPo("张三","1234"));
    }
}

此时调用此方法, @Transactional会失效,testMapper.insert(sysUserOrgPo)不会回滚,根本原因是@Transactional的实现通过的AOP实现,也就是动态代理实现,如果方法上的修饰符都是非public的时候,那么将不会创建代理对象,所以事务也就不生效

失效第二种

在类内部调用调用类内部@Transactional标注的方法。这种情况下也会导致事务不开启

@Service
public class TestServiceImpl {
    @Autowired
    TestMapper testMapper;
    
   @Transactional
   public void insert(SysUserOrgPo sysUserOrgPo) {
        int re = testMapper.insert(sysUserOrgPo);
        if (re > 0) {
            throw new BaseException("发生异常")
        }
        
        testMapper.insert(new SysUserOrgPo("张三","1234"));
    }
     public void testInnerInvoke(){
        //内部调用事务方法,@Transactional失效
        testServiceImpl.insertTestInnerInvoke();
    }
}

如果在类内部调用类内部的事务方法,这个调用事务方法的过程并不是通过代理对象来调用的,而是直接通过this对象来调用方法,绕过了代理对象,肯定就是没有代理逻辑了 

失效第三种 

事务方法内部捕捉了异常,没有抛出新的异常,导致事务操作不会进行回滚,原因是实现逻辑是只有捕获到异常才会回滚事务,列举源码如下

try {
  retVal = invocation.proceedWithInvocation();
} catch (Throwable var20) {
    // 事务回滚
    this.completeTransactionAfterThrowing(txInfo, var20);
    throw var20;
} finally {
    this.cleanupTransactionInfo(txInfo);
}
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]