当前位置: 首页 > news >正文

(39)AOP的实际案例

事务处理

项目中的事务控制是在所难免的。在一个业务流程当中,可能需要多条DML语句共同完成,为了保证数据的安全,这多条DML语句要么同时成功,要么同时失败。这就需要添加事务控制的代码。例如以下伪代码:

class业务类1{publicvoid业务方法1(){try{// 开启事务startTransaction();// 执行核心业务逻辑step1();step2();step3();....// 提交事务commitTransaction();}catch(Exceptione){// 回滚事务rollbackTransaction();}}publicvoid业务方法2(){try{// 开启事务startTransaction();// 执行核心业务逻辑step1();step2();step3();....// 提交事务commitTransaction();}catch(Exceptione){// 回滚事务rollbackTransaction();}}publicvoid业务方法3(){try{// 开启事务startTransaction();// 执行核心业务逻辑step1();step2();step3();....// 提交事务commitTransaction();}catch(Exceptione){// 回滚事务rollbackTransaction();}}}class业务类2{publicvoid业务方法1(){try{// 开启事务startTransaction();// 执行核心业务逻辑step1();step2();step3();....// 提交事务commitTransaction();}catch(Exceptione){// 回滚事务rollbackTransaction();}}publicvoid业务方法2(){try{// 开启事务startTransaction();// 执行核心业务逻辑step1();step2();step3();....// 提交事务commitTransaction();}catch(Exceptione){// 回滚事务rollbackTransaction();}}publicvoid业务方法3(){try{// 开启事务startTransaction();// 执行核心业务逻辑step1();step2();step3();....// 提交事务commitTransaction();}catch(Exceptione){// 回滚事务rollbackTransaction();}}}//......

可以看到,这些业务类中的每一个业务方法都是需要控制事务的,而控制事务的代码又是固定的格式,都是:

try{// 开启事务startTransaction();// 执行核心业务逻辑//......// 提交事务commitTransaction();}catch(Exceptione){// 回滚事务rollbackTransaction();}

这个控制事务的代码就是和业务逻辑没有关系的“交叉业务”。以上伪代码当中可以看到这些交叉业务的代码没有得到复用,并且如果这些交叉业务代码需要修改,那必然需要修改多处,难维护,怎么解决?可以采用AOP思想解决。可以把以上控制事务的代码作为环绕通知,切入到目标类的方法当中。接下来我们做一下这件事,有两个业务类,如下:

packagecom.powernode.spring6.biz;importorg.springframework.stereotype.Component;@Component// 业务类publicclassAccountService{// 转账业务方法publicvoidtransfer(){System.out.println("正在进行银行账户转账");}// 取款业务方法publicvoidwithdraw(){System.out.println("正在进行取款操作");}}
packagecom.powernode.spring6.biz;importorg.springframework.stereotype.Component;@Component// 业务类publicclassOrderService{// 生成订单publicvoidgenerate(){System.out.println("正在生成订单");}// 取消订单publicvoidcancel(){System.out.println("正在取消订单");}}

注意,以上两个业务类已经纳入spring bean的管理,因为都添加了@Component注解。
接下来我们给以上两个业务类的4个方法添加事务控制代码,使用AOP来完成:

packagecom.powernode.spring6.biz;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.springframework.stereotype.Component;@Aspect@Component// 事务切面类publicclassTransactionAspect{@Around("execution(* com.powernode.spring6.biz..*(..))")publicvoidaroundAdvice(ProceedingJoinPointproceedingJoinPoint){try{System.out.println("开启事务");// 执行目标proceedingJoinPoint.proceed();System.out.println("提交事务");}catch(Throwablee){System.out.println("回滚事务");}}}

你看,这个事务控制代码是不是只需要写一次就行了,并且修改起来也没有成本。编写测试程序:

packagecom.powernode.spring6.test;importcom.powernode.spring6.biz.AccountService;importcom.powernode.spring6.biz.OrderService;importcom.powernode.spring6.service.Spring6Configuration;importorg.junit.Test;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassAOPTest2{@TestpublicvoidtestTransaction(){ApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Spring6Configuration.class);OrderServiceorderService=applicationContext.getBean("orderService",OrderService.class);AccountServiceaccountService=applicationContext.getBean("accountService",AccountService.class);// 生成订单orderService.generate();// 取消订单orderService.cancel();// 转账accountService.transfer();// 取款accountService.withdraw();}}

执行结果:

通过测试可以看到,所有的业务方法都添加了事务控制的代码。

安全日志

需求是这样的:项目开发结束了,已经上线了。运行正常。客户提出了新的需求:凡事在系统中进行修改操作的,删除操作的,新增操作的,都要把这个人记录下来。因为这几个操作是属于危险行为。例如有业务类和业务方法:

packagecom.powernode.spring6.biz;importorg.springframework.stereotype.Component;@Component//用户业务publicclassUserService{publicvoidgetUser(){System.out.println("获取用户信息");}publicvoidsaveUser(){System.out.println("保存用户");}publicvoiddeleteUser(){System.out.println("删除用户");}publicvoidmodifyUser(){System.out.println("修改用户");}}
packagecom.powernode.spring6.biz;importorg.springframework.stereotype.Component;// 商品业务类@ComponentpublicclassProductService{publicvoidgetProduct(){System.out.println("获取商品信息");}publicvoidsaveProduct(){System.out.println("保存商品");}publicvoiddeleteProduct(){System.out.println("删除商品");}publicvoidmodifyProduct(){System.out.println("修改商品");}}

注意:已经添加了@Component注解。
接下来我们使用aop来解决上面的需求:编写一个负责安全的切面类

packagecom.powernode.spring6.biz;importorg.aspectj.lang.JoinPoint;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Before;importorg.aspectj.lang.annotation.Pointcut;importorg.springframework.stereotype.Component;@Component@AspectpublicclassSecurityAspect{@Pointcut("execution(* com.powernode.spring6.biz..save*(..))")publicvoidsavePointcut(){}@Pointcut("execution(* com.powernode.spring6.biz..delete*(..))")publicvoiddeletePointcut(){}@Pointcut("execution(* com.powernode.spring6.biz..modify*(..))")publicvoidmodifyPointcut(){}@Before("savePointcut() || deletePointcut() || modifyPointcut()")publicvoidbeforeAdivce(JoinPointjoinpoint){System.out.println("XXX操作员正在操作"+joinpoint.getSignature().getName()+"方法");}}

代码解释:

  • @Pointcut注解是定义一个切点表达式,用于指定哪些方法需要被拦截。
  • execution(…)匹配方法执行的连接点。
    • @Before:定义一个前置通知,在目标方法执行之前运行。
      切点表达式"savePointcut() || deletePointcut() || modifyPointcut()",表示当满足任一切点(save、delete 或 modify)时触发此通知。
@TestpublicvoidtestSecurity(){ApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Spring6Configuration.class);UserServiceuserService=applicationContext.getBean("userService",UserService.class);ProductServiceproductService=applicationContext.getBean("productService",ProductService.class);userService.getUser();userService.saveUser();userService.deleteUser();userService.modifyUser();productService.getProduct();productService.saveProduct();productService.deleteProduct();productService.modifyProduct();}

http://www.jsqmd.com/news/154258/

相关文章:

  • 2025年郑州美业培训学校排行榜,新测评精选美业教育机构推荐 - 工业品牌热点
  • (41)事务属性(建议在数据库深入学习)
  • YOLO目标检测模型训练太慢?试试我们的高性能GPU套餐
  • YOLO训练成本太高?我们送你免费GPU token体验包
  • (42)事务的两种开发模式
  • 生成式AI移动应用测试工程方法论
  • 2025白刚玉定制口碑前十强,你选对了吗?磨料/金刚砂/碳化硅/白刚玉/不锈钢灰/精密铸造砂/棕刚玉/铬刚玉/黑碳化硅白刚玉厂家有哪些 - 品牌推荐师
  • YOLO + Triton推理服务器:构建高并发检测服务
  • 2025年谁主沉浮?顶尖重型货架厂家综合评比,重型板材存放架/重型货架超强承重/重型模具货架/伸缩悬臂货架/重型货架重型货架定制厂家哪家强 - 品牌推荐师
  • Compose笔记(六十四)--LottieAnimation
  • HTTP的简介和原理 - saboyou1
  • 2025.12.28博客
  • 智能 Agent 的概念建模与系统特征分析-从传统程序到自主智能体的范式演进
  • vue 甘特图 vxe-gantt table 可视化依赖线的使用,可视化拖拽创建连接线的用法
  • Cloudflare Wrangler CLI 备忘
  • 论文阅读(十二月第四周)
  • 做不出IT毕设,我是废物吗?
  • YOLO模型支持Logstash日志处理管道
  • YOLO模型训练支持CutOut与HideAndSeek图像遮挡增强
  • 2025年三合一过滤洗涤干燥机厂家排名:哈氏合金/搪瓷设备专业制造商推荐 - mypinpai
  • 从“拔网线“看互联网大厂的安全攻防:黑灰产攻击原理与防御实战
  • Next AI Draw.io 核心实现深度分析
  • HTTP的原理 - saboyou1
  • 2025年优质尼龙拖链品牌排行榜,尼龙拖链与其他材质拖链对比优势在哪? - mypinpai
  • 12/28-正式1级打卡题1(课后)
  • YOLO目标检测准确率提升技巧:混合精度训练+GPU支持
  • YOLOv9-SPPF结构详解:为何它更适合边缘GPU设备?
  • 鸿蒙原生系列之动画效果(关键帧动画)
  • 2025郑州西餐培训推荐TOP5权威榜单:甄选靠谱机构避坑指南,新手入门必看 - myqiye
  • YOLO训练日志分析:如何通过GPU利用率诊断瓶颈