【Spring AOP】结合日志面向切面编程 两种写法

news/2025/2/23 5:05:23/

概念

        这里需要提前了解什么是Spring的AOP(Aspect Oriented Programming)。是在OOP(面向对象)思想的一种拓展思想。简单来说就是将某个代码块嵌入到其它的代码块中。笔者先前学Spring也有学什么IoC啊AOP啊,但实际上没有用过、就那听过学过没啥用的。。没会儿就忘记了。那种也就是个了解,好像知道是个什么事儿?当时还特地去背关于AOP的那几个专有名词?现在想想有点好笑。

        不过还是需要提前巩固知道几个词。看完了下面的这三个词的用法就开始进入模拟实战。

切面(Aspect):由切点和通知组成。即使用@Aspect注解的类

切点(Pointcut):可以限定访问修饰符、类全限定名、方法名和参数类型,甚至用于匹配注解

通知(Advice):想要嵌入到其它代码块的代码块。其中包括五种类型。

        @Before(目标方法执行前执行)

        @After(目标方法执行后执行)

        @AfterReturning(目标方法返回结果后不出现异常才执行)

        @AfterThrowin(出现异常才执行)

        @Around(以上都包括)

引入依赖

<!-- Spring Boot -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- 简化开发 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency><!-- AOP -->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId>
</dependency>

创建注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {/*** 描述** @return {String}*/String value();}

业务代码

@Slf4j
@RestController
@RequestMapping("/log")
public class LogController {@Log("AOP测试")@GetMapping("/aspect")public void aspect() {log.info("进入AOP测试方法");for(int i = 0; i < 10; ++i) {log.info("执行业务逻辑{}", i);}log.info("结束AOP测试方法");}}

编写切面

有切点

@Slf4j
@Component
@Aspect
public class LogAspect {@Autowiredprivate ApplicationEventPublisher publisher;/*** 切点* 这里面主要掌握两个东西:*  1、如果使用注解的话就需要获取注解的类全限定名*  2、执行的execution表达式(这是比较重要掌握的) 这里面有四个参数 需要知道的是*也可以表示前缀或者后缀 和SQL中的"%"类似*      一、方法的访问权限修饰符(public/protected/default/private)*      二、方法的返回值类型*      三、类的全限定名(包名.类名)*      四、*(..)的第一个表示方法名;括号内表示参数,而两个点表示接收任何参数类型*/@Pointcut("@annotation(com.chf.annotation.Log) && execution(public * com.chf.controller.*Controller.*(..))")public void logPointcut() {}@SneakyThrows@Around("logPointcut()")public Object around(ProceedingJoinPoint point) {// 获取注解完后解析其内部的属性MethodSignature signature = (MethodSignature) point.getSignature();log.info("获取注解,{}", signature); // void com.chf.controller.LogController.aspect()Method method = signature.getMethod();log.info("获取注解的方法,{}", method);// public void com.chf.controller.LogController.aspect()Log logAnnotation = method.getAnnotation(Log.class);log.info("获取使用注解的value参数,{}", logAnnotation.value()); // AOP测试// 发送异步事件Long startTime = System.currentTimeMillis();Object o;try {o = point.proceed();} finally {// 这里可以使用发布订阅模式发布异步事件 至于使用哪一种发布订阅模式就看业务场景了Long endTime = System.currentTimeMillis();publisher.publishEvent(new LogEvent("事件处理的时间是:" + (endTime - startTime) + "ms"));}return o;}
}

无切点

@Slf4j
@Component
@Aspect
public class LogAspect {@Autowiredprivate ApplicationEventPublisher publisher;@SneakyThrows@Around("@annotation(logAnnotation) && execution(public * com.chf.controller.*Controller.*(..))")public Object around(ProceedingJoinPoint point, Log logAnnotation) {// 获取注解完后解析其内部的属性MethodSignature signature = (MethodSignature) point.getSignature();log.info("获取注解,{}", signature); // void com.chf.controller.LogController.aspect()Method method = signature.getMethod();log.info("获取注解的方法,{}", method);// public void com.chf.controller.LogController.aspect()Log logAnnotation = method.getAnnotation(Log.class);log.info("获取使用注解的value参数,{}", logAnnotation.value()); // AOP测试// 发送异步事件Long startTime = System.currentTimeMillis();Object o;try {o = point.proceed();} finally {Long endTime = System.currentTimeMillis();publisher.publishEvent(new LogEvent("事件处理的时间是:" + (endTime - startTime) + "ms"));}return o;}
}

测试

        不了解Spring的发布订阅模式可以看这篇博文:https://blog.csdn.net/m0_65563175/article/details/131899828?spm=1001.2014.3001.5501


http://www.ppmy.cn/news/1009631.html

相关文章

【博客689】监控进程的自愿与非自愿上下文切换

监控进程的自愿与非自愿上下文切换 场景 有时候遇到机器没有性能瓶颈&#xff0c;但是进程出现性能瓶颈&#xff0c;这时候往往需要进程级别的监控 监控手段&#xff1a;process_exporter https://github.com/ncabatoff/process-exporter 监控相关指标&#xff1a;context_swi…

STL容器适配器 -- priority_queue(使用+实现)(C++)

priority_queue priority_queue 简单介绍priority_queue 使用内置类型测试自定义类型测试 priority_queue 模拟实现仿函数&#xff08;less、greater&#xff09; priority_queue 简单介绍 优先级队列是一种容器适配器。类似于堆&#xff0c;可以随时插入元素&#xff0c;只能…

4、数据清洗

4、数据清洗 前面我们处理的数据实际上都是已经被处理好的规整数据&#xff0c;但是在大数据整个生产过程中&#xff0c;需要先对数据进行数据清洗&#xff0c;将杂乱无章的数据整理为符合后面处理要求的规整数据。 数据去重 1.删除重复数据groupby().count()&#xff1a;可以…

Stripe订阅支付和WebHook事件

&#xff08;哪里有天才&#xff0c;我是把别人喝咖啡的功夫都用在工作上的。——鲁迅&#xff09; stripe Stripe是由20多岁的两兄弟Patrick Collison和John Collison创办的Stripe为公司提供网上支付的解决方案。Stripe向服务的公司收取每笔交易的2.9%加上30美分的手续费 订…

Java面向对象学习第三部分

一、Static修饰符 static是静态的意思&#xff0c;基本概念如下&#xff1a; Static分类&#xff1a; 一般我们分类都是按照是否使用static修饰进行分类。分为静态变量&#xff08;类变量&#xff09;、实例变量。 静态变量和实例变量的比较&#xff1a; 比较&#xff0c;…

【C语言】详解getchar和putchar的使用方法

&#x1f388;个人主页&#xff1a;库库的里昂 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;C语言初阶 ✨其他专栏&#xff1a;代码小游戏 &#x1f91d;希望作者的文章能对你有所帮助&#xff0c;有不足的地方请在评论…

Microsoft Message Queuing Denial-of-Service Vulnerability

近期官方公布了一个MSMQ的拒绝服务漏洞&#xff0c;可能因为网络安全设备的更新&#xff0c;影响业务&#xff0c;值得大家关注。 漏洞具体描述参见如下&#xff1a; Name: Microsoft Message Queuing Denial-of-Service Vulnerability Description: Microsoft Message Queuing…

python list相关操作

列表的方法 1、append(value) 只能在末尾追加一个要素。但是&#xff0c;append支持列表的嵌套 2、index(value) 返回第一个出现value的索引 index(value,index):返回index之后第一个出现value的索引 3、clear() 清空列表 4、copy() 复制一个新的列表 5、count(value) 统计列表…