news 2026/7/7 17:28:12

(39)AOP的实际案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(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();}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/3 1:38:04

(41)事务属性(建议在数据库深入学习)

事务属性包括哪些事务中的重点属性: 事务传播行为事务隔离级别事务超时只读事务设置出现哪些异常回滚事务设置出现哪些异常不回滚事务 事务传播行为 什么是事务的传播行为? 在service类中有a()方法和b()方法,a()方法上有事务,b()方…

作者头像 李华
网站建设 2026/7/5 19:46:14

ITU-T G.723.1 双速率语音编码器技术深度分析与负载特性报告

ITU-T G.723.1 双速率语音编码器技术深度分析与负载特性报告 1. 引言 1.1 背景与标准演进 在数字通信技术飞速发展的20世纪90年代中期,随着互联网的兴起和公共交换电话网络(PSTN)向分组交换网络的过渡,对于在极低比特率下传输高…

作者头像 李华
网站建设 2026/7/4 5:37:43

YOLO在无人机视觉中的应用:轻量模型+低功耗GPU方案

YOLO在无人机视觉中的应用:轻量模型低功耗GPU方案 在消费级与工业级无人机快速普及的今天,一个核心挑战日益凸显:如何让飞行器“看得清、反应快、能耗低”?尤其是在自主导航、避障和目标追踪等关键任务中,传统基于规则…

作者头像 李华
网站建设 2026/7/3 10:41:57

YOLO在冰川变化监测中的应用:遥感图像分析实践

YOLO在冰川变化监测中的应用:遥感图像分析实践技术背景与核心价值 在全球气候变暖的背景下,冰川加速消融已成为影响海平面、水资源和生态安全的关键变量。传统监测手段依赖人工解译卫星影像或实地勘测,不仅周期长、成本高,还难以应…

作者头像 李华
网站建设 2026/7/3 10:40:58

YOLO模型训练支持CutOut与HideAndSeek图像遮挡增强

YOLO模型训练支持CutOut与HideAndSeek图像遮挡增强 在工业质检、智能监控和自动驾驶等真实场景中,目标被部分遮挡几乎是常态——货架前走过的员工遮住了商品,车流中互相掩映的车辆,或是产线上夹具对零件的覆盖。这些情况对目标检测模型构成了…

作者头像 李华
网站建设 2026/7/3 10:40:09

YOLO模型推理延迟高?可能是你的GPU没配对

YOLO模型推理延迟高?可能是你的GPU没配对 在一条自动化质检产线上,每分钟要处理上千件产品。摄像头以60帧/秒的速度拍摄图像,后台系统必须在16毫秒内完成每一帧的缺陷检测——否则就会漏检、误判,直接导致生产线停摆。工程师部署了…

作者头像 李华