基于切面实现自定义事务
一、介绍
仿造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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了