AOP统一日志打印处理
在日常开发工作中,我们免不了要打印很多log。而大部分需要输出的log又是重复的(例如传入参数,返回值)。
因此,通过AOP方式来进行日志管理可以减少很多代码量,也更加优雅。
Springboot通过AOP方式(@Aspect)和Javassist优雅地进行日志输出管理。
主要使用技术:Aspect,Javassist
package com.xinyartech.erp.system.aop; import java.lang.reflect.Modifier; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; import com.alibaba.fastjson.JSON;
import com.xinyartech.erp.core.util.Util; import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo; /**
* 通过spring aop实现service方法执行时间监控
*
* @author Lynch
*
*/
@Aspect
@Component
public class WebLogAop {
private static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WebLogAop.class); private static ThreadLocal<String> threadLocal = new ThreadLocal<String>(); //public static final String POINT = "execution (* com.xinyartech.erp.*.web.*.*(..))"; @Pointcut("(execution (* com.xinyartech.erp.*.web.*.*(..)))")
public void webLog(){ } /**
* 前置通知
* @param joinPoint 切点
* @throws Throwable 异常
*/
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
String uuid = Util.getUUID();
threadLocal.set(uuid); String classType = joinPoint.getTarget().getClass().getName();
Class<?> clazz = Class.forName(classType);
String clazzName = clazz.getName();
log.info(String.format("[%s] 类名:%s", uuid, clazzName));
String methodName = joinPoint.getSignature().getName();
log.info(String.format("[%s] 方法名:%s", uuid, methodName));
String[] paramNames = getFieldsName(this.getClass(), clazzName, methodName);
Object[] args = joinPoint.getArgs();
for(int k=0; k<args.length; k++){
log.info("[" + uuid + "] 参数名:" + paramNames[k] + ",参数值:" + JSON.toJSONString(args[k]));
}
} /**
* 后置通知
* 打印返回值日志
* @param ret 返回值
* @throws Throwable 异常
*/
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(JoinPoint joinPoint, Object ret) throws Throwable {
String uuid = threadLocal.get();
String classType = joinPoint.getTarget().getClass().getName();
Class<?> clazz = Class.forName(classType);
String clazzName = clazz.getName();
log.info(String.format("[%s] 类名:%s", uuid, clazzName));
String methodName = joinPoint.getSignature().getName();
log.info(String.format("[%s] 方法名:%s", uuid, methodName));
log.info(String.format("[%s] 返回值 : %s", uuid, JSON.toJSONString(ret)));
log.info("*****************************************");
} /**
* 得到方法参数的名称
* @param cls 类
* @param clazzName 类名
* @param methodName 方法名
* @return 参数名数组
* @throws NotFoundException 异常
*/
private static String[] getFieldsName(Class<?> cls, String clazzName, String methodName) throws NotFoundException {
ClassPool pool = ClassPool.getDefault();
ClassClassPath classPath = new ClassClassPath(cls);
pool.insertClassPath(classPath); CtClass cc = pool.get(clazzName);
CtMethod cm = cc.getDeclaredMethod(methodName);
MethodInfo methodInfo = cm.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
String[] paramNames = new String[cm.getParameterTypes().length];
int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
for (int i = 0; i < paramNames.length; i++){
paramNames[i] = attr.variableName(i + pos); //paramNames即参数名
}
return paramNames;
}
}
AOP统一日志打印处理的更多相关文章
- SpringBoot统一日志打印
统一日志打印 @Slf4j @Aspect @Component public class ControllerLog { private static final ThreadLocal<Lo ...
- 【Java分享客栈】超简洁SpringBoot使用AOP统一日志管理-纯干货干到便秘
前言 请问今天您便秘了吗?程序员坐久了真的会便秘哦,如果偶然点进了这篇小干货,就麻烦您喝杯水然后去趟厕所一边用左手托起对准嘘嘘,一边用右手滑动手机看完本篇吧. 实现 本篇AOP统一日志管理写法来源于国 ...
- 简单的aop实现日志打印(切入点表达式)
Spring中可以使用注解或XML文件配置的方式实现AOP. 1.导入jar包 com.springsource.net.sf.cglib -2.2.0.jar com.springsource.or ...
- 基于XML配置的AOP实现日志打印
Spring中可以使用注解或XML文件配置的方式实现AOP.1.导入jar包 com.springsource.net.sf.cglib -2.2.0.jar com.springsource.org ...
- SpringBoot | 第二十四章:日志管理之AOP统一日志
前言 上一章节,介绍了目前开发中常见的log4j2及logback日志框架的整合知识.在很多时候,我们在开发一个系统时,不管出于何种考虑,比如是审计要求,或者防抵赖,还是保留操作痕迹的角度,一般都会有 ...
- Spring AOP统一日志 全量日志
Spring AOP 切面@Around注解的具体使用 lichuangcsdn 2019-02-19 23:21:36 63936 收藏 61分类专栏: Spring 文章标签: Spring AO ...
- PHP框架(如:laravel、yii2、thinkPHP5)中统一异常处理及统一日志打印
背景: 现在写接口服务应用有一个很通用的需求,想通过日志.或者监控的形式监测的接口的运行情况,比如耗时.请求参数.响应结果.和前端联调接口时或者排查线上问题时日志必不可少,特别是现场日志. 应用运行时 ...
- springboot aop + logback + 统一异常处理 打印日志
1.src/resources路径下新建logback.xml 控制台彩色日志打印 info日志和异常日志分不同文件存储 每天自动生成日志 结合myibatis方便日志打印(debug模式) < ...
- Spring AOP实现统一日志输出
目的: 统一日志输出格式 思路: 1.针对不同的调用场景定义不同的注解,目前想的是接口层和服务层. 2.我设想的接口层和服务层的区别在于: (1)接口层可以打印客户端IP,而服务层不需要 (2)接口层 ...
随机推荐
- Go之第三方库ini
文章转自 快速开始 my.ini # possible values : production, development app_mode = development [paths] # Path t ...
- Cut Ribbon
Polycarpus has a ribbon, its length is n. He wants to cut the ribbon in a way that fulfils the follo ...
- MODULE BUILD FAILED: ERROR: COULDN’T FIND PRESET “ES2015” RELATIVE TO DIRECTORY
npm run dev 遇到报错: Module build failed: Error: Couldn't find preset "es2015" relative to di ...
- hdu1695(莫比乌斯反演+容斥)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题目是求 在区间[a,b]选一个数x,区间[c,d]选一个数y,求满足gcd(x,y) = k ...
- hdu 1281 棋盘游戏(二分图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 每行每列作为节点,给可以放车的点将对应的行列连边,最多可放置的车即为建二分图后的最大匹配,跑一边 ...
- Abp中打开错误信息输出
Abp默认是不向客户端输出错误日志的,导致有些内部报错既不能中断,也没有信息输出.此时打开日志输出开关即可.在xxModule类中PreInitialize()方法里 Configuration.Mo ...
- Abaqus 载荷分类(部分)
目录 1. 集中载荷 1.1 集中载荷施加方法 1.2 定义集中跟随力 1.3 指定文件定义集中节点力 2. 分布载荷 2.1 分布载荷分类 3. 热载荷 3.1 模拟热辐射 3.2 直接定义热流量 ...
- Spring - Spring Boot - Actuator Web 访问开启
1. 概述 打开 Spring Boot Actuator 的 Web 访问 2. 场景 之前看 Spring 的时候, 曾经想了解当时的配置 后来发现, 确实有这么个工具 刚开始发现, 除了 act ...
- CSS学习(11)常规流
盒模型:规定单个盒子的规则 视觉格式化模型(布局规则):页面中多个盒子的排列规则 三种方式: 1.常规流 2.浮动 3.定位 常规流布局 常规流 也可以叫做 文档流.普通文档流.常规文档流 所 ...
- Docker配置阿里云镜像源
Docker默认拉取镜像是从这里拉取(https://hub.docker.com/),拉取的速度让人...,所以是配置国内镜像源,拉取速度十分惊人 一.版本要求 Docker版本:1.10以上 二. ...