@Transactional实现原理
Transactional是spring中定义的事务注解,在方法或类上加该注解开启事务。主要是通过反射获取当前对象的注解信息,利用AOP(代理模式)对编程式事务进行封装实现
//
// 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<? extends Throwable>[] rollbackFor() default {};String[] rollbackForClassName() default {};Class<? extends Throwable>[] noRollbackFor() default {};String[] noRollbackForClassName() default {};
}
手动实现事务自定义注解
自定义注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {//自定义注解的属性int id() default 0;String name() default "默认名称";String[] arrays() default {};String title() default "默认标题";
}
封装编程式事务
@Component
@Scope("prototype")
public class TransactionUtil {// 全局接受事务状态private TransactionStatus transactionStatus;// 获取事务源@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;// 开启事务public TransactionStatus begin() {System.out.println("开启事务");transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());return transactionStatus;}// 提交事务public void commit(TransactionStatus transaction) {System.out.println("提交事务");if (dataSourceTransactionManager != null) {dataSourceTransactionManager.commit(transaction);}}public void rollback(TransactionStatus transaction) {System.out.println("回滚事务");if (dataSourceTransactionManager != null) {dataSourceTransactionManager.rollback(transaction);}}
}
AOP触发事务
@Component
@Aspect
public class AopTransaction {@Autowiredprivate TransactionUtil transactionUtil;private TransactionStatus transactionStatus;/*** 环绕通知,在方法 前---后 处理事情** @param pjp 切入点*/@Around("execution(* com.sl.service.*.*(..))")public void around(ProceedingJoinPoint pjp) throws Throwable {// 获取方法的注解MyAnnotation annotation = this.getMethodMyAnnotation(pjp);// 判断是否需要开启事务transactionStatus = begin(annotation);// 调用目标代理对象方法pjp.proceed();// 判断关闭事务commit(transactionStatus);}/*** 获取代理方法上的事务注解** @param pjp* @return* @throws Exception*/private MyAnnotation getMethodMyAnnotation(ProceedingJoinPoint pjp) throws Exception {// 获取代理对象的方法String methodName = pjp.getSignature().getName();// 获取目标对象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 {@AutowiredTestMapper testMapper;@Transactionalvoid 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 {@AutowiredTestMapper testMapper;@Transactionalpublic 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);
}