🧑💻作者名称:DaenCode
🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。
😎人生感悟:尝尽人生百味,方知世间冷暖。
📖所属专栏:SpringBoot实战
系列文章目录
标题一文带你学会使用SpringBoot+Avue实现短信通知功能(含重要文件代码)一张思维导图带你学会Springboot创建全局异常、自定义异常一张思维导图带你打通SpringBoot自定义拦截器的思路28个SpringBoot项目中常用注解,日常开发、求职面试不再懵圈一张思维导图带你学会SpringBoot、Vue前后端分离项目线上部署一张思维导图带你学会使用SpringBoot中的Schedule定时发送邮件一张思维导图带你学会使用SpringBoot异步任务实现下单校验库存
文章目录
思维导图
🌟AOP介绍
基本概念:在不改变原有功能的逻辑,增加新的功能。
应用场景:
- 权限控制
- 日志处理
- 事务控制
下面以对产品数据增删改查功能,进行日志管理功能为例,对AOP中的核心概念作出介绍,请参考下表
概念解析对应日志管理功能核心关注点业务逻辑的主要功能,应用程序主要关注的部分产品数据的增删改查横切关注点与核心关注点相关但不属于核心关注点的功能,在系统的多个模块或组件中散布记录产品操作的日志通知在特定切入点执行时要执行的代码,实现横切关注点的具体逻辑。可以在目标方法执行之前、之后或抛出异常时执行执行记录日志的代码连接点可以插入通知的特定点,通常是方法执行的位置产品表操作的方法切入点通过表达式或规则定义的连接点的集合。确定了哪些连接点与通知关联起来选择所有的插入、更新或删除操作的连接点集合切面横切关注点和通知的组合,将通知应用到切入点匹配的连接点上包含记录日志的通知和定义切入点的规则目标被通知的对象或类,即应用程序中执行具体操作的对象或方法对产品数据作出操作的对象或方法织入将切面应用到目标对象上,创建新的代理对象的过程。可以在编译时、加载时或运行时进行将日志管理切面应用到产品表操作的目标对象上,以记录日志
🌟具体实现步骤
数据准备
创建产品表、以及日志表,并向产品表添加相关数据。
CREATETABLE`product`(`id`int(11)NOTNULL,`name`varchar(100)CHARACTERSET utf8mb4 COLLATE utf8mb4_general_ci NULLDEFAULTNULL,`price`decimal(10,2)NULLDEFAULTNULL,`stock`int(11)NULLDEFAULTNULL,PRIMARYKEY(`id`)USINGBTREE)ENGINE=InnoDBCHARACTERSET= utf8mb4 COLLATE= utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS =1;-- ------------------------------ Records of product-- ----------------------------INSERTINTO`product`VALUES(1,'苹果13',10.99,50);INSERTINTO`product`VALUES(2,'小米10',19.99,99);INSERTINTO`product`VALUES(3,'华为mate20',5.99,19);CREATETABLE`log`(`id`int(10)NOTNULLAUTO_INCREMENT,`operation`varchar(255)CHARACTERSET utf8mb4 COLLATE utf8mb4_general_ci NULLDEFAULTNULL,`data`varchar(255)CHARACTERSET utf8mb4 COLLATE utf8mb4_general_ci NULLDEFAULTNULL,`operate_time`datetimeNULLDEFAULTNULL,PRIMARYKEY(`id`)USINGBTREE)ENGINE=InnoDBAUTO_INCREMENT=1CHARACTERSET= utf8mb4 COLLATE= utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS =1;
引入相关依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
创建实体类
Product类
publicclassProductimplementsSerializable{privateInteger id;privateString name;privateBigDecimal price;privateInteger stock;}
Log类
publicclassLogimplementsSerializable{privateInteger id;privateString operation;privateString data;privateTimestamp operateTime;}
自定义注解@LogTip
自定义注解,用于标记记录日志的方法。
@Documented@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceLogTip{Stringvalue()default"";}
定义切面类
切面类由
切点PointCut+通知Advice
共同构成。有关于通知的类型以及解释,可以
查看思维导图中的通知节点
。有关于JoinPoint的API见下表
API描述getSignature()获取连接点的签名,返回一个MethodSignature对象getArgs()获取连接点方法的参数数组getTarget()获取目标对象getThis()获取当前代理对象toShortString()生成连接点的简短描述toLongString()生成连接点的详细描述getStaticPart()获取静态连接点部分getKind()获取连接点的类型getSourceLocation()获取连接点所在位置的源代码位置
@Component@AspectpublicclassLogAspect{@AutowiredprivateLogMapper logMapper;@Pointcut("@annotation(com.shoanjen.redis.annotation.LogTip)")publicvoidpointCut(){}@AfterReturning("pointCut()")publicvoidgetLogInfo(JoinPoint point)throwsThrowable{// 获取方法参数列表Object[] args = point.getArgs();//获取自定义注解上的描述信息MethodSignature methodSignature=(MethodSignature) point.getSignature();Method method=methodSignature.getMethod();LogTip annotation=method.getAnnotation(LogTip.class);String desc=annotation.value();// 获取操作的数据String data =Arrays.toString(args);// 记录日志saveLog(desc, data);}privatevoidsaveLog(String desc,String data){Log log =newLog();
log.setOperation(desc);
log.setData(data);
log.setOperateTime(newTimestamp(System.currentTimeMillis()));
logMapper.save(log);}}
LogMapper
publicinterfaceLogMapper{voidsave(Log log);}
<insertid="save"parameterType="com.shoanjen.redis.model.Log"keyColumn="id"keyProperty="id"useGeneratedKeys="true">
INSERT INTO log(operation, data, operate_time) VALUES (#{operation}, #{data}, #{operateTime});
</insert>
ProductController
这里以上一篇文章一张思维导图带你学会使用SpringBoot异步任务实现下单校验库存中的产品下单功能为例子,对其记录日志。
@RestController@RequestMapping("/api/v1/product")publicclassProductController{@AutowiredprivateProductService productService;@AutowiredprivateValidateTask validateTask;@LogTip("产品下单")@RequestMapping("order")publicJsonDataorder(@RequestParamint productId,@RequestParamint quantity)throwsExecutionException,InterruptedException{Future<Boolean> validateResult=validateTask.validateStock(productId,quantity);System.out.println(validateResult.get());Boolean flag=false;//判断异步任务是否完成if(validateResult.isDone()){try{
flag=validateResult.get();}catch(Exception e){
flag=false;}}if(flag){returnJsonData.buildSuccess("下单成功");}else{returnJsonData.buildError("下单失败,库存不足");}}}
🌟最终测试
接口请求测试
日志表查看
🌟写在最后
有关于SpringBoot使用AOP实现日志管理功能到此就结束了。感谢大家的阅读,希望大家在评论区对此部分内容散发讨论,便于学到更多的知识。
版权归原作者 DaenCode 所有, 如有侵权,请联系我们删除。