又被逼着优化代码,这次我干掉了出入参 Log日志
本文收录在个人博客:www.chengxy-nds.top,技术资源共享。
最近技术部突然刮起一阵 review 代码的小风,挨个项目组过代码,按理说这应该是件挺好的事,让别人指出自己代码中的不足,查缺补漏,对提升自身编码能力有很大帮助,毕竟自己审查很容易“陶醉”在自己写的代码里。

不过,代码 review 的详细程度令人发指,一行一行的分析,简直就是个培训班啊。不夸张的说,如果我村里仅有县重点小学学历的四大爷,来听上一个月后,保证能上手开发,666~
既然组内气氛到这了,咱也得行动起来,要不哪天评审到我的代码,让人家指指点点的心里多少有点不舒服,与其被动优化代码不如主动出击~
选优化代码的方向,方法入参和返回结果日志首当其冲,每个方法都会有这两个日志,一大堆冗余的代码,而且什么样的打印格式都有,非常的杂乱。
public OrderDTO getOrder(OrderVO orderVO, String name) {
log.info("订单详情入参:orderVO={},name={}", JSON.toJSONString(orderVO), name);
OrderDTO orderInfo = orderService.getOrderInfo(orderVO);
log.info("订单详情结果:orderInfo={}", JSON.toJSONString(orderInfo));
return orderInfo;
}
下边我们利用 AOP 实现请求方法的入参、返回结果日志统一打印,避免日志打印格式杂乱,同时减少业务代码量。
一、自定义注解
自定义切面注解@PrintlnLog 用来输出日志,注解权限 @Target({ElementType.METHOD}) 限制只在方法上使用,注解中只有一个参数 description ,用来自定义方法输出日志的描述。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface PrintlnLog {
/**
* 自定义日志描述信息文案
*
* @return
*/
String description() default "";
}
二、切面类
接下来编写@PrintlnLog 注解对应的切面实现,doBefore()中输出方法的自定义描述、入参、请求方式、请求url、被调用方法的位置等信息,doAround() 中打印方法返回结果。
注意: 如何想指定切面在哪个环境执行,可以用@Profile 注解,只打印某个环境的日志。
@Slf4j
@Aspect
@Component
//@Profile({"dev"}) //只对某个环境打印日志
public class LogAspect {
private static final String LINE_SEPARATOR = System.lineSeparator();
/**
* 以自定义 @PrintlnLog 注解作为切面入口
*/
@Pointcut("@annotation(com.chengxy.unifiedlog.config.PrintlnLog)")
public void PrintlnLog() {
}
/**
* @param joinPoint
* @author fu
* @description 切面方法入参日志打印
* @date 2020/7/15 10:30
*/
@Before("PrintlnLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String methodDetailDescription = this.getAspectMethodLogDescJP(joinPoint);
log.info("------------------------------- start --------------------------");
/**
* 打印自定义方法描述
*/
log.info("Method detail Description: {}", methodDetailDescription);
/**
* 打印请求入参
*/
log.info("Request Args: {}", JSON.toJSONString(joinPoint.getArgs()));
/**
* 打印请求方式
*/
log.info("Request method: {}", request.getMethod());
/**
* 打印请求 url
*/
log.info("Request URL: {}", request.getRequestURL().toString());
/**
* 打印调用方法全路径以及执行方法
*/
log.info("Request Class and Method: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
}
/**
* @param proceedingJoinPoint
* @author xiaofu
* @description 切面方法返回结果日志打印
* @date 2020/7/15 10:32
*/
@Around("PrintlnLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
String aspectMethodLogDescPJ = getAspectMethodLogDescPJ(proceedingJoinPoint);
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
/**
* 输出结果
*/
log.info("{},Response result : {}", aspectMethodLogDescPJ, JSON.toJSONString(result));
/**
* 方法执行耗时
*/
log.info("Time Consuming: {} ms", System.currentTimeMillis() - startTime);
return result;
}
/**
* @author xiaofu
* @description 切面方法执行后执行
* @date 2020/7/15 10:31
*/
@After("PrintlnLog()")
public void doAfter(JoinPoint joinPoint) throws Throwable {
log.info("------------------------------- End --------------------------" + LINE_SEPARATOR);
}
/**
* @param joinPoint
* @author xiaofu
* @description @PrintlnLog 注解作用的切面方法详细细信息
* @date 2020/7/15 10:34
*/
public String getAspectMethodLogDescJP(JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
return getAspectMethodLogDesc(targetName, methodName, arguments);
}
/**
* @param proceedingJoinPoint
* @author xiaofu
* @description @PrintlnLog 注解作用的切面方法详细细信息
* @date 2020/7/15 10:34
*/
public String getAspectMethodLogDescPJ(ProceedingJoinPoint proceedingJoinPoint) throws Exception {
String targetName = proceedingJoinPoint.getTarget().getClass().getName();
String methodName = proceedingJoinPoint.getSignature().getName();
Object[] arguments = proceedingJoinPoint.getArgs();
return getAspectMethodLogDesc(targetName, methodName, arguments);
}
/**
* @param targetName
* @param methodName
* @param arguments
* @author xiaofu
* @description 自定义注解参数
* @date 2020/7/15 11:51
*/
public String getAspectMethodLogDesc(String targetName, String methodName, Object[] arguments) throws Exception {
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder("");
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description.append(method.getAnnotation(PrintlnLog.class).description());
break;
}
}
}
return description.toString();
}
}
三、应用
我们在需要打印入参和返回结果日志的方法,加上@PrintlnLog注解,并添加自定义方法描述。
@RestController
@RequestMapping
public class OrderController {
@Autowired
private OrderService orderService;
@PrintlnLog(description = "订单详情Controller")
@RequestMapping("/order")
public OrderDTO getOrder(OrderVO orderVO, String name) {
OrderDTO orderInfo = orderService.getOrderInfo(orderVO);
return orderInfo;
}
}
代码里去掉 log.info日志打印,加上 @PrintlnLog 看一下效果,清晰明了。

Demo GitHub地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-aop-unifiedlog
原创不易,燃烧秀发输出内容,如果有一丢丢收获,点个赞鼓励一下吧!
整理了几百本各类技术电子书,送给小伙伴们。关注公号回复【666】自行领取。和一些小伙伴们建了一个技术交流群,一起探讨技术、分享技术资料,旨在共同学习进步,如果感兴趣就加入我们吧!
又被逼着优化代码,这次我干掉了出入参 Log日志的更多相关文章
- svn update -r m path 代码还原到某个版本(这样之前的log日志也就没了,也就是清空log日志)
[root@ok 资料库]# svn log 简历 ------------------------------------------------------------------------ r ...
- 为duilib的MenuDemo增加消息响应,优化代码和显示效果
转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/38253297 第一部分 我在前一段时间研究了怎么制作duilib的菜单, ...
- Webpack 4教程:为什么要优化代码
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://wanago.io/2018/07/30/webpack-4-course-part ...
- Android 性能优化:使用 Lint 优化代码、去除多余资源
前言 在保证代码没有功能问题,完成业务开发之余,有追求的程序员还要追求代码的规范.可维护性. 今天,以“成为优秀的程序员”为目标的拭心将和大家一起精益求精,学习使用 Lint 优化我们的代码. 什么是 ...
- 如何优化代码中大量的if/else,switch/case?
前言 随着项目的迭代,代码中存在的分支判断可能会越来越多,当里面涉及到的逻辑比较复杂或者分支数量实在是多的难以维护的时候,我们就要考虑下,有办法能让这些代码变得更优雅吗? 正文 使用枚举 这里我们简单 ...
- JavaScript工作机制:V8 引擎内部机制及如何编写优化代码的5个诀窍
概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下 ...
- JavaScript是如何工作的02:深入V8引擎&编写优化代码的5个技巧
概述 JavaScript引擎是执行 JavaScript 代码的程序或解释器.JavaScript引擎可以实现为标准解释器,或者以某种形式将JavaScript编译为字节码的即时编译器. 以为实现J ...
- 通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数--菜单功能'menufile
通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁 ...
- 通过游戏学python 3.6 第一季 第八章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数
通过游戏学python 3.6 第一季 第八章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账 ...
随机推荐
- 算法题解:最小的K个数(海量数据Top K问题)
[本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 题目 输入 n ...
- MongoDB快速入门教程 (4.3)
4.3.Mongoose模块化 4.3.1.为什么要进行模块化拆分? 模块化拆分的目的是为了代码的复用,让整个项目的结构更加清晰,举个例子:当数据库中的集合变多的时候,例如有课程.订单.分类.教师等多 ...
- Oracle数据库中,误删除或者修改数据恢复方法
在我们实际工作中,误删除或者修改Oracle数据库中的数据,怎么办呢?这里给大家分享一种解决办法.假如你误操作的时间不超过30分钟(数据库默认的回滚保持段里的数据时间,可以在pl/sql执行窗口按ct ...
- SpringBoot中Service实现类添加@Service却任然无法注入的问题
最近一直在研究Spring Boot.从GitHub上下载了一个my-Blog源码,一边看,一边自己尝试去实现,结果掉在坑了,研究了近一周才爬出来,特地来这博客园记录下来,一是避免自己在放这样的错误, ...
- GAN网络从入门教程(二)之GAN原理
在一篇博客GAN网络从入门教程(一)之GAN网络介绍中,简单的对GAN网络进行了一些介绍,介绍了其是什么,然后大概的流程是什么. 在这篇博客中,主要是介绍其数学公式,以及其算法流程.当然数学公式只是简 ...
- css3盒子模型中的box-sizing属性的使用_box sizing常用的3种属性
box-sizing属性用来定义元素的width和height所表示的区域,该属性一般有三种值:content-box.border-box.inherit.其中inherit表示box-sizing ...
- H5和原生的职责划分
前言 在JSBridge实现后,前端网页与原生的交互已经通了,接下来就要开始规划API,明确需要提供哪一些功能来供前端调用. 但是在这之前,还有一点重要工作需要做: 明确H5与Native的职责划分, ...
- Redis的持久化——RDB和AOF
推荐阅读 Redis 持久化之RDB和AOF --来自ITDragon龙 Redis Persistence --来自Redis官网文档
- 从零开始学Electron笔记(二)
在之前的文章我们简单介绍了一下Electron可以用WEB语言开发桌面级应用,接下来我们继续说一下Electron的菜单创建和事件绑定. 我们接上一章的代码继续编写,上一章代码 https://www ...
- day22 作业
1 统计文件夹大小 def get_filesize(file_path): count = 0 res=None files_sum = os.listdir(file_path) for file ...