基于切面实现自定义事务
一、介绍
仿造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