@Transactional实现原理及失效的三种情况
@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 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); }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。