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

56_AOP

AOP使用案例

如何进行数据库和Redis中的数据同步?/ 你在项目的那些地方使用了aop?
答:可以通过Aop操作来实现数据库和Redis中的数据同步。/ 通过Aop操作来实现数据库和Redis中的数据同步。
可以定义一个切面类,通过对控制器下的所有方法进行环绕通知。
数据同步有两种情况

  1. 一种是服务器接收get请求,首先从Redis中取,没有对应的key再执行方法从数据库中获取数据并添加到Redis中;
  2. 第二种情况是服务器接收写请求,包括增删改,这时就需要先对Redis中的数据进行扫描,对特定key对应的的数据进行删除清空,再执行方法修改数据库中的内容(没有考虑再次将数据库中的数据同步到Redis是因为:如果服务器接收到任一get请求,都会自动进行同步)
import cn.cnmd.redis.RedisService;
import com.alibaba.fastjson2.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;import java.lang.reflect.Method;
import java.time.Duration;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;@Aspect
@Component
public class RedisCacheAspect {private static Random random = new Random();@Autowiredprivate RedisService redisService;@Pointcut("execution(* cn.ctmd.electric.*.controller.*(..))")private void pointcut() {}@Around("pointcut()")public Object around(ProceedingJoinPoint pjp) throws Throwable {Signature signature = pjp.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();String className = method.getDeclaringClass().getSimpleName();String methodName = method.getName();if (method.isAnnotationPresent(GetMapping.class)) {// get请求Object[] args = pjp.getArgs();String cacheKey = className + "::" + methodName + JSON.toJSONString(args);if (Boolean.TRUE.equals(redisService.hasKey(cacheKey))) {return redisService.get(cacheKey);} else {synchronized (this) {if (Boolean.FALSE.equals(redisService.hasKey(cacheKey))) {Object value = pjp.proceed();long expireTime = Duration.ofMinutes(5).toMillis() + random.nextInt(1000);redisService.set(cacheKey, value, expireTime, TimeUnit.MILLISECONDS);return value;} else {return redisService.get(cacheKey);}}}} else {if (method.isAnnotationPresent(PostMapping.class) || method.isAnnotationPresent(PutMapping.class) || method.isAnnotationPresent(DeleteMapping.class)) {List<String> list = redisService.scan(className, 50);if (list != null) {redisService.delete(list.toString());}}}return pjp.proceed();}
}

AOP

概念:面向切面编程

术语

  • 连接点:被拦截到的程序的执行点(在spring中就是被拦截到的方法)
  • 切入点:对需要进行拦截的条件的定义(某个位置)
  • 通知、增强:为切入点添加二维的功能
  • 目标对象:要被增强的对象
  • 织入:将切面和业务逻辑对象连接起来,并创建通知代理的过程
  • 代理:被织入后产生的结果类
  • 切面:一个横切关注点的模块化(一个切面类的代称)

类型

  1. 前置通知
  2. 后置通知
  3. 环绕通知
  4. 异常抛出通知
  5. 最终通知(少见)

一个切面类

@Aspect
public class AspectJAdvice {@Before(value = "execution(* com.qf.spring.aop.service..*(..))")public void before(JoinPoint jp){Object[] args = jp.getArgs(); //获取方法参数Signature signature = jp.getSignature(); //获取签名if(signature instanceof MethodSignature){ //如果签名是方法签名Method method = ((MethodSignature) signature).getMethod(); //获取方法String methodName = method.getName();String className = method.getDeclaringClass().getName();System.out.println("准备执行方法:" + className + "." + methodName + ",参数:" + Arrays.toString(args));}}@AfterReturning(value = "execution(* com.qf.spring.aop.service..*(..))", returning = "returnValue")public void after(JoinPoint jp, Object returnValue){Object[] args = jp.getArgs(); //获取方法参数Signature signature = jp.getSignature(); //获取签名if(signature instanceof MethodSignature){ //如果签名是方法签名Method method = ((MethodSignature) signature).getMethod(); //获取方法String methodName = method.getName();String className = method.getDeclaringClass().getName();System.out.println("执行完方法:" + className + "." + methodName + ",参数:" + Arrays.toString(args) + ",得到返回值:" + returnValue);}}@AfterThrowing(value = "execution(* com.qf.spring.aop.service..*(..))", throwing = "t")public void exception(JoinPoint jp, Throwable t){Object[] args = jp.getArgs(); //获取方法参数Signature signature = jp.getSignature(); //获取签名if(signature instanceof MethodSignature){ //如果签名是方法签名Method method = ((MethodSignature) signature).getMethod(); //获取方法String methodName = method.getName();String className = method.getDeclaringClass().getName();System.out.println("执行方法时:" + className + "." + methodName + ",参数:" + Arrays.toString(args) + ",发生了异常:" + t.getMessage());}}@Around("execution(* com.qf.spring.aop.service..*(..))")public Object around(ProceedingJoinPoint pjp) throws Throwable {Object[] args = pjp.getArgs();//获取方法的参数Object target = pjp.getTarget(); //获取代理对象Signature signature = pjp.getSignature(); //获取签名if(signature instanceof MethodSignature) { //如果签名是方法签名Method method = ((MethodSignature) signature).getMethod(); //获取被拦截的方法对象String methodName = method.getName();String className = method.getDeclaringClass().getName();try {System.out.println("准备执行方法:" + className + "." + methodName + ",参数:" + Arrays.toString(args));Object returnValue = method.invoke(target, args);System.out.println("执行完方法:" + className + "." + methodName + ",参数:" + Arrays.toString(args) + ",得到返回值:" + returnValue);return returnValue;} catch (Throwable t){System.out.println("执行方法时:" + className + "." + methodName + ",参数:" + Arrays.toString(args) + ",发生了异常:" + t.getMessage());throw t;}}return null;}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python试讲
  • 【Python体验】第五天:目录搜索、数据爬虫(评论区里写作业)
  • tcp为啥是三次握手,不是四次、两次?
  • 【ESP01开发实例】-ESP-01驱动DHT11和DH22传感器
  • 软件测试个人求职简历该怎么写,模板在这里
  • 文档编辑协作神器,全方位解决方案,灵活部署赋能个人与企业-onlyoffice
  • springboot+ mybatis + oracle 代码生成器代码
  • Python面试整理-异常处理
  • 区块链核心概念与技术架构简介
  • 软考:软件设计师 — 9.数据流图
  • 使用Langchain构建简单的数据库Agent
  • 【Rust光年纪】探索Rust语言中的音视频处理库:功能与应用概述
  • python实现微信聊天图片DAT文件还原
  • LeetCode 572.另一棵树的子树 C写法
  • Day3-shell脚本编程
  • [Vue CLI 3] 配置解析之 css.extract
  • css布局,左右固定中间自适应实现
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • js中forEach回调同异步问题
  • MobX
  • MySQL数据库运维之数据恢复
  • python 学习笔记 - Queue Pipes,进程间通讯
  • tab.js分享及浏览器兼容性问题汇总
  • 阿里云前端周刊 - 第 26 期
  • 初识 beanstalkd
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 多线程事务回滚
  • 和 || 运算
  • 那些年我们用过的显示性能指标
  • 微信小程序--------语音识别(前端自己也能玩)
  • 栈实现走出迷宫(C++)
  • NLPIR智能语义技术让大数据挖掘更简单
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • # Redis 入门到精通(九)-- 主从复制(1)
  • #Linux(Source Insight安装及工程建立)
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • #预处理和函数的对比以及条件编译
  • #知识分享#笔记#学习方法
  • (2)Java 简介
  • (a /b)*c的值
  • (分布式缓存)Redis哨兵
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (一)u-boot-nand.bin的下载
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)iOS字体
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • ****三次握手和四次挥手
  • .NET CF命令行调试器MDbg入门(一)
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET开源纪元:穿越封闭的迷雾,拥抱开放的星辰
  • .NET是什么