当前位置: 首页 > 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.zskr.cn/news/169361.html

相关文章:

  • 2025年郑州美业培训学校排行榜,新测评精选美业教育机构推荐 - 工业品牌热点
  • YOLO训练成本太高?我们送你免费GPU token体验包
  • 生成式AI移动应用测试工程方法论
  • YOLO模型训练支持CutOut与HideAndSeek图像遮挡增强
  • 做不出IT毕设,我是废物吗?
  • 2025年三合一过滤洗涤干燥机厂家排名:哈氏合金/搪瓷设备专业制造商推荐 - mypinpai
  • Next AI Draw.io 核心实现深度分析
  • 鸿蒙原生系列之动画效果(关键帧动画)
  • 2025郑州西餐培训推荐TOP5权威榜单:甄选靠谱机构避坑指南,新手入门必看 - myqiye
  • YOLO在冰川变化监测中的应用:遥感图像分析实践
  • 2025年度哈尔滨卫生间瓷砖行业口碑品牌排行榜 - 工业品牌热点
  • YOLO模型推理延迟高?可能是你的GPU没配对
  • 2025年终北京GEO优化公司推荐:聚焦垂直行业案例的5强榜单权威评测 - 品牌推荐
  • Spring AI Alibaba实战训练营-19 基于Graph的电商商品信息自动丰富化Agent开发指南
  • 当算法遇上极限:2025 年计算机科学六大颠覆性突破
  • 2025年终天津GEO优化公司推荐:聚焦垂直行业深耕的5强深度解析与推荐。 - 品牌推荐
  • 教育培训微信小程序计算机毕设(源码+lw+部署文档+讲解等)
  • YOLO模型训练支持Gradient Clipping防止梯度爆炸
  • Elasticsearch部署Linux优化:揭秘高效部署技巧,助力面试脱颖而出!
  • 基于微信小程序的校园综合服务平台计算机毕设(源码+lw+部署文档+讲解等)
  • 好写作AI:给你的论文一键穿上“高定学术西装”,秒变顶级期刊范儿!
  • YOLOv9-Slim轻量版发布:移动端推理速度再提升
  • 耳分解 双极定向
  • 三菱 FX5U定位模块5轴 2轴插补伺服 包括三菱FX5U伺服5轴程序2轴插补,昆仑通态触摸屏...
  • 2025年哈尔滨热门卫生间瓷砖推荐:高性价比瓷砖、低价格瓷砖靠谱品牌有哪些? - 工业品牌热点
  • 2025年终GEO公司电话推荐:聚焦垂直行业案例的5家优质服务商深度解析 - 品牌推荐
  • 2025年终GEO公司电话推荐:聚焦垂直行业案例的5强服务商榜单深度解析。 - 品牌推荐
  • 大树科技联系方式:基于工业知识重构的AI品牌可见性构建指南 - 品牌推荐
  • 外弹道仿真程序:质点弹道模型与Matlab实现
  • 郑州西点培训哪家专业、哪家可靠、哪家合适?年度TOP5推荐榜单 - myqiye