运用Spring Aop,一个注解实现日志记录
运用Spring Aop,一个注解实现日志记录
1. 介绍
我们都知道Spring框架的两大特性分别是 IOC
(控制反转)和 AOP
(面向切面),这个是每一个Spring学习视频里面一开始都会提到的。在日常项目中,我们也会经常使用IOC控制反转,但是却感觉AOP很少会运用到。其实AOP大有用处,甚至可以让你偷偷懒。
举一个例子,假如现在要让你记录每一个请求的请求IP,请求的方法,请求路径,请求的参数,返回参数,你会怎么做?你会想,那简单啊,我直接 log.info("xxxx") 输出日志不行吗,简单!可是你要想清楚,每个请求请求的方法不一定是同一个,有一些请求可能请求编辑方法,另外一些请求可能请求登录方法,这么多方法,你每一个方法下面都重复写了差不多6,7行重复代码,你觉得这好吗?
这里,如果我们使用Aop来记录日志,那是再好不过了。我们可以看看一个方法的执行过程来理解AOP。
下面再来看使用AOP后的执行过程。
AOP是面向切面编程,面向切面思想就是让我们把程序想象成一条一条管道连接起来的大管道,而AOP就是在管道和管道之间的过滤网,能够在不影响管道的情况下对管道中传输的数据进行记录,修改。
使用AOP我们可以很方便地进行操作日志记录,性能日志记录,请求日志记录,事务操作,安全管理等。这么说可能很抽象,再详细点说就是各种日志记录我们可以利用AOP来进行记录,而不用在业务逻辑代码中插入,安全管理就是我们可以在请求进来前对请求中的数据进行解密,在请求返回的时候对数据进行加密。这么说AOP很像Java里面的拦截器,过滤器和监听器的结合。
具体AOP的原理就不细讲了,那是另外一篇文章了,有关于动态代理。
2. 实践
说了这么多,大白话就是AOP能让我们在不影响原代码的基础上,对代码功能进行添加,修改
在实现日志记录功能前,我们要先复习一下 Spring Aop 里面的通知顺序(连接点,通知还不知道是什么的,先去B站看一下Spring初级教程)。
先把Aop的starter依赖添加进pom文件中。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.1 定义注解
那现在我们来自定义一个注解,目的是标注该注解的方法将会记录调用该方法的请求信息
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface MyLog {
String value() default "";
}
注解不是本篇重点,有兴趣的童鞋可以搜一下。
2.2 切面类
定义我们的日志记录切面类,切面类中记录请求的信息。
@Component
@Aspect
@Slf4j
public class LogAspect {
//切入点为自定义注解
@Pointcut("@annotation(com.example.springaopdemo.demo2.MyLog)")
public void MyLog(){}
@Before("MyLog()")
public void Before(JoinPoint jp){
//获取HttpServletRequest对象
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert requestAttributes != null;
HttpServletRequest request = requestAttributes.getRequest();
log.info("==========请求信息==========");
log.info("请求链接 : {}",request.getRequestURL().toString());
log.info("Http Method : {}",request.getMethod());
log.info("Class Method : {}.{}",jp.getSignature().getDeclaringTypeName(),jp.getSignature().getName());
log.info("Ip : {}",request.getRemoteAddr());
log.info("Args : {}", Arrays.asList(jp.getArgs()));
}
@Around("MyLog()")
public Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
log.info("执行时间 : {} ms", System.currentTimeMillis() - startTime);
log.info("返回参数 : {}", result);
return result;
}
}
通过 @Around
环绕通知我们可以进行简单的性能记录,如果加上 Oshi
我们甚至可以记录执行该方法前后的CPU,内存占用率。
Oshi是Java的免费基于JNA的操作系统和硬件信息库,Github地址是:https://github.com/oshi/oshi
它的优点是不需要安装任何其他本机库,并且旨在提供一种跨平台的实现来检索系统信息,例如操作系统版本,进程,内存和CPU使用率,磁盘和分区,设备,传感器等。
2.3 编写测试方法
编写一个简单的请求,请求需要一个User对象的请求体,返回一个Map结果。
@RestController
@Slf4j
public class Controller {
@PostMapping("/test")
@MyLog
public Map<String, Object> testAop(@RequestBody User user){
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("errorMsg","success");
return map;
}
}
2.4 运行结果
使用IDEA自带的Http Client来测试api
结果:
可以看到通过利用AOP,我们没有修改Controller中的代码,就可以实现对Controller中每个方法请求信息的日志记录功能。
而且我们还能够指定该切面类是在生产环境还是开发环境下生效,只需要在切面类上添加注解。
@Profile({"dev"})
然后在配置文件中定义 spring.profiles.active
的属性即可。
3. 总结
因为学习了Spring后,虽然知道有AOP这个东西,但是却从来没有真正的在实际项目中运用,这几天研究日志记录,却发现AOP在日志记录中的妙用,甚至可以利用AOP在对代码无侵入的情况下,进行参数数据的加密和解密操作。但是,虽然说AOP使用方便,但是不能够滥用,毕竟AOP底层使用动态代理,而动态代理要做到对方法的修改就肯定要使用到反射,反射会对性能有影响。
4. 参考文章
(7 封私信 / 66 条消息) 在一个完整的项目中,会用AOP技术么,能用简单易懂的方式说明下什么是AOP么? - 知乎 (zhihu.com)
【SpringBoot】AOP应用实例_sysu_lluozh-CSDN博客
(20条消息) Springboot Aop 自定义注解、切面_张同学的博客-CSDN博客_springboot 自定义注解切面
运用Spring Aop,一个注解实现日志记录的更多相关文章
- spring aop通过注解实现日志记录
首先是几个概念:连接点(Joinpoint).切点(Pointcut).增强(Advice).切面(Aspect) 另外也要使用到注解. 需求:通过注解定义LogEnable.然后程序运行能够识别定义 ...
- 利用Spring AOP自定义注解解决日志和签名校验
转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先 ...
- spring AOP自定义注解 实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- (转)利用Spring AOP自定义注解解决日志和签名校验
一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: ...
- spring AOP自定义注解方式实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- Spring Boot 2.X(八):Spring AOP 实现简单的日志切面
AOP 1.什么是 AOP ? AOP 的全称为 Aspect Oriented Programming,译为面向切面编程,是通过预编译方式和运行期动态代理实现核心业务逻辑之外的横切行为的统一维护的一 ...
- spring aop 使用注解方式总结
spring aop的注解方式:和xml的配置方式略有区别,详细如下: 1.首先还是建立需要的切面类:切面类里面定义好切点配置,以及所有的需要实现的通知方法. /** * */ package com ...
- Spring aop+自定义注解统一记录用户行为日志
写在前面 本文不涉及过多的Spring aop基本概念以及基本用法介绍,以实际场景使用为主. 场景 我们通常有这样一个需求:打印后台接口请求的具体参数,打印接口请求的最终响应结果,以及记录哪个用户在什 ...
- Spring AOP使用注解记录用户操作日志
最后一个方法:核心的日志记录方法 package com.migu.cm.aspect; import com.alibaba.fastjson.JSON; import com.migu.cm.do ...
随机推荐
- 【LeetCode】942. DI String Match 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 【LeetCode】521. Longest Uncommon Subsequence I 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 【剑指Offer】删除链表中重复的结点 解题报告(Python)
[剑指Offer]删除链表中重复的结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interview ...
- codeforce-424C. Magic Formulas(数学)
C. Magic Formulas time limit per test:2 seconds memory limit per test:256 megabytes input stan ...
- 看完这篇 Linux 权限后,通透了!
我们在使用 Linux 的过程中,或多或少都会遇到一些关于使用者和群组的问题,比如最常见的你想要在某个路径下执行某个指令,会经常出现这个错误提示 . permission denied 反正我大概率见 ...
- Jmeter环境变量配置你不得不知道的事情
在安装Jmeter的过程中大家肯定需要配置环境,但是为什么要配置JDK的环境变量呢?大家有没有好奇过,有没有仔细去像一下呢,其实在安装Jmeter前,大家应该都知道Jmeter是我们JAVA开发的,J ...
- 如何用微信小程序,每天给自己赚个鸡腿?
假期如果实在无聊的话,那跟随田同学的脚步上架一个小程序吧. 话说:谁不想拥有一个自己的小程序呢?既可以赚点小钱又可以长长见识. 不懂小程序的小白能不能做出来呢?那来对了,这个教程就是针对小白的. 今天 ...
- Selenium_获取元素文本、属性值、尺寸(8)
from selenium import webdriver driver = webdriver.Chrome() driver.maximize_window() driver.get(" ...
- vi中使用鼠标右键插入时进入(insert)visual模式
使用vim插入外面复制的内容时,用右键点击后,并未将内容粘贴进去,而是进入了(insert)visual模式,解决方法:先shift+enter进入普通模式输入 set mouse-=a然后再i进入i ...
- Shell统计每个单词出现的个数
题目链接 题目描述 写一个 bash脚本以统计一个文本文件 nowcoder.txt 中每个单词出现的个数. 为了简单起见,你可以假设: nowcoder.txt只包括小写字母和空格. 每个单词只由小 ...