基于切面实现自定义事务

一、介绍

仿造spring中的@Transactional注解实现简易版的事务。通过spring中的aop拦截所有带自定义事务注解的方法去实现事务的控制。

二、步骤

  • 创建一个自定义事务注解CustomTransactional.java

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface CustomTransactional {
    }
    
  • 事务注解切面拦截类CustomTransactionalInterceptor.java

    @Aspect
    @Component
    public class CustomTransactionalInterceptor {
    
        @Autowired
        private PlatformTransactionManager platformTransactionManager;
    
        @Autowired
        private TransactionDefinition transactionDefinition;
    
        // 匹配所有方法上加上@CustomTransactional注解的方法
        @Pointcut(value = "@annotation(com.linmt.transaction.annocations.CustomTransactional)")
        public void transactionalPointCut() {
        }
    
        @Before(value = "transactionalPointCut()")
        // 开启事务
        public void beforeTransactionalHandle() {
            TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
            TransactionStatusContext.setTransactionStatus(transactionStatus);
        }
    
        @AfterReturning(value = "transactionalPointCut()")
        // 方法正常返回
        public void afterReturningTransactionalHandle() {
            TransactionStatus transactionStatus = TransactionStatusContext.getTransactionStatus();
            platformTransactionManager.commit(transactionStatus);
        }
    
        @AfterThrowing(value = "transactionalPointCut()", throwing = "e")
        // 方法执行抛出异常
        public void afterThrowingTransactionalHandle(Throwable e) {
            TransactionStatus transactionStatus = TransactionStatusContext.getTransactionStatus();
            platformTransactionManager.rollback(transactionStatus);
    
            // 此处可以根据异常类型进行判断是否回滚
        }
    }
    

    创建一个TransactionStatus上下文类

     public class TransactionStatusContext {
         private static ThreadLocal<TransactionStatus> threadLocal = new ThreadLocal<>();
    
         public static void setTransactionStatus(TransactionStatus transactionStatus) {
             threadLocal.set(transactionStatus);
         }
    
         public static TransactionStatus getTransactionStatus() {
             return threadLocal.get();
         }
    
         public static void clearTransactionStatus() {
             threadLocal.remove();
         }
     }
    
  • 新建一个service类

    @Service
    public class UserServiceImpl implements IUserService {
        @Autowired
        private UserMapper userMapper;
    
        @Override
        @CustomTransactional
        public void insertOne(UserPo userPo) {
            userMapper.insertOne(userPo);
    
            int i = 1/0;
        }
    }
    

三、效果

  • 不加事务注解

​ 数据库数据正常插入

  • 加事务注解

数据并不能正常插入

  • 修改事务注解拦截类里面抛异常时,正常commit事务

​ 数据可以正常提交

四、源码

https://github.com/1277463718lmt/custom-transactional-demo.git

posted @ 2023-05-04 22:55  linmt  阅读(151)  评论(0编辑  收藏  举报