又被逼着优化代码,这次我干掉了出入参 Log日志

系统
最近技术部突然刮起一阵 review 代码的小风,挨个项目组过代码,按理说这应该是件挺好的事,让别人指出自己代码中的不足,查缺补漏,对提升自身编码能力有很大帮助,毕竟自己审查很容易“陶醉”在自己写的代码里。

本文转载自微信公众号「程序员内点事」,作者程序员内点事。转载本文请联系程序员内点事公众号。

最近技术部突然刮起一阵 review 代码的小风,挨个项目组过代码,按理说这应该是件挺好的事,让别人指出自己代码中的不足,查缺补漏,对提升自身编码能力有很大帮助,毕竟自己审查很容易“陶醉”在自己写的代码里。

[[334348]]

 

不过,代码 review 的详细程度令人发指,一行一行的分析,简直就是个培训班啊。不夸张的说,如果我村里仅有县重点小学学历的四大爷,来听上一个月后,保证能上手开发,666~

既然组内气氛到这了,咱也得行动起来,要不哪天评审到我的代码,让人家指指点点的心里多少有点不舒服,与其被动优化代码不如主动出击~

选优化代码的方向,方法入参和返回结果日志首当其冲,每个方法都会有这两个日志,一大堆冗余的代码,而且什么样的打印格式都有,非常的杂乱。

  1. public OrderDTO getOrder(OrderVO orderVO, String name) { 
  2.  
  3.         log.info("订单详情入参:orderVO={},name={}", JSON.toJSONString(orderVO), name); 
  4.  
  5.         OrderDTO orderInfo = orderService.getOrderInfo(orderVO); 
  6.  
  7.         log.info("订单详情结果:orderInfo={}", JSON.toJSONString(orderInfo)); 
  8.  
  9.         return orderInfo; 

下边我们利用 AOP 实现请求方法的入参、返回结果日志统一打印,避免日志打印格式杂乱,同时减少业务代码量。

一、自定义注解

自定义切面注解@PrintlnLog 用来输出日志,注解权限 @Target({ElementType.METHOD}) 限制只在方法上使用,注解中只有一个参数 description ,用来自定义方法输出日志的描述。

  1. @Retention(RetentionPolicy.RUNTIME) 
  2. @Target({ElementType.METHOD}) 
  3. @Documented 
  4. public @interface PrintlnLog { 
  5.  
  6.     /** 
  7.      * 自定义日志描述信息文案 
  8.      * 
  9.      * @return 
  10.      */ 
  11.     String description() default ""

二、切面类

接下来编写@PrintlnLog 注解对应的切面实现,doBefore()中输出方法的自定义描述、入参、请求方式、请求url、被调用方法的位置等信息,doAround() 中打印方法返回结果。

注意: 如何想指定切面在哪个环境执行,可以用@Profile 注解,只打印某个环境的日志。

  1. @Slf4j 
  2. @Aspect 
  3. @Component 
  4. //@Profile({"dev"}) //只对某个环境打印日志 
  5. public class LogAspect { 
  6.  
  7.     private static final String LINE_SEPARATOR = System.lineSeparator(); 
  8.  
  9.     /** 
  10.      * 以自定义 @PrintlnLog 注解作为切面入口 
  11.      */ 
  12.     @Pointcut("@annotation(com.chengxy.unifiedlog.config.PrintlnLog)"
  13.     public void PrintlnLog() { 
  14.     } 
  15.  
  16.     /** 
  17.      * @param joinPoint 
  18.      * @author fu 
  19.      * @description 切面方法入参日志打印 
  20.      * @date 2020/7/15 10:30 
  21.      */ 
  22.     @Before("PrintlnLog()"
  23.     public void doBefore(JoinPoint joinPoint) throws Throwable { 
  24.  
  25.         ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 
  26.         HttpServletRequest request = attributes.getRequest(); 
  27.  
  28.         String methodDetailDescription = this.getAspectMethodLogDescJP(joinPoint); 
  29.  
  30.         log.info("------------------------------- start --------------------------"); 
  31.         /** 
  32.          * 打印自定义方法描述 
  33.          */ 
  34.         log.info("Method detail Description: {}", methodDetailDescription); 
  35.         /** 
  36.          * 打印请求入参 
  37.          */ 
  38.         log.info("Request Args: {}", JSON.toJSONString(joinPoint.getArgs())); 
  39.         /** 
  40.          * 打印请求方式 
  41.          */ 
  42.         log.info("Request method: {}", request.getMethod()); 
  43.         /** 
  44.          * 打印请求 url 
  45.          */ 
  46.         log.info("Request URL: {}", request.getRequestURL().toString()); 
  47.  
  48.         /** 
  49.          * 打印调用方法全路径以及执行方法 
  50.          */ 
  51.         log.info("Request Class and Method: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); 
  52.     } 
  53.  
  54.     /** 
  55.      * @param proceedingJoinPoint 
  56.      * @author xiaofu 
  57.      * @description 切面方法返回结果日志打印 
  58.      * @date 2020/7/15 10:32 
  59.      */ 
  60.     @Around("PrintlnLog()"
  61.     public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { 
  62.  
  63.         String aspectMethodLogDescPJ = getAspectMethodLogDescPJ(proceedingJoinPoint); 
  64.  
  65.         long startTime = System.currentTimeMillis(); 
  66.  
  67.         Object result = proceedingJoinPoint.proceed(); 
  68.         /** 
  69.          * 输出结果 
  70.          */ 
  71.         log.info("{},Response result  : {}", aspectMethodLogDescPJ, JSON.toJSONString(result)); 
  72.  
  73.         /** 
  74.          * 方法执行耗时 
  75.          */ 
  76.         log.info("Time Consuming: {} ms", System.currentTimeMillis() - startTime); 
  77.  
  78.         return result; 
  79.     } 
  80.  
  81.     /** 
  82.      * @author xiaofu 
  83.      * @description 切面方法执行后执行 
  84.      * @date 2020/7/15 10:31 
  85.      */ 
  86.     @After("PrintlnLog()"
  87.     public void doAfter(JoinPoint joinPoint) throws Throwable { 
  88.         log.info("------------------------------- End --------------------------" + LINE_SEPARATOR); 
  89.     } 
  90.  
  91.     /** 
  92.      * @param joinPoint 
  93.      * @author xiaofu 
  94.      * @description @PrintlnLog 注解作用的切面方法详细细信息 
  95.      * @date 2020/7/15 10:34 
  96.      */ 
  97.     public String getAspectMethodLogDescJP(JoinPoint joinPoint) throws Exception { 
  98.         String targetName = joinPoint.getTarget().getClass().getName(); 
  99.         String methodName = joinPoint.getSignature().getName(); 
  100.         Object[] arguments = joinPoint.getArgs(); 
  101.         return getAspectMethodLogDesc(targetName, methodName, arguments); 
  102.     } 
  103.  
  104.     /** 
  105.      * @param proceedingJoinPoint 
  106.      * @author xiaofu 
  107.      * @description @PrintlnLog 注解作用的切面方法详细细信息 
  108.      * @date 2020/7/15 10:34 
  109.      */ 
  110.     public String getAspectMethodLogDescPJ(ProceedingJoinPoint proceedingJoinPoint) throws Exception { 
  111.         String targetName = proceedingJoinPoint.getTarget().getClass().getName(); 
  112.         String methodName = proceedingJoinPoint.getSignature().getName(); 
  113.         Object[] arguments = proceedingJoinPoint.getArgs(); 
  114.         return getAspectMethodLogDesc(targetName, methodName, arguments); 
  115.     } 
  116.  
  117.     /** 
  118.      * @param targetName 
  119.      * @param methodName 
  120.      * @param arguments 
  121.      * @author xiaofu 
  122.      * @description 自定义注解参数 
  123.      * @date 2020/7/15 11:51 
  124.      */ 
  125.     public String getAspectMethodLogDesc(String targetName, String methodName, Object[] arguments) throws Exception { 
  126.         Class targetClass = Class.forName(targetName); 
  127.         Method[] methods = targetClass.getMethods(); 
  128.         StringBuilder description = new StringBuilder(""); 
  129.         for (Method method : methods) { 
  130.             if (method.getName().equals(methodName)) { 
  131.                 Class[] clazzs = method.getParameterTypes(); 
  132.                 if (clazzs.length == arguments.length) { 
  133.                     description.append(method.getAnnotation(PrintlnLog.class).description()); 
  134.                     break; 
  135.                 } 
  136.             } 
  137.         } 
  138.         return description.toString(); 
  139.     } 

三、应用

我们在需要打印入参和返回结果日志的方法,加上@PrintlnLog注解,并添加自定义方法描述。

  1. @RestController 
  2. @RequestMapping 
  3. public class OrderController { 
  4.  
  5.     @Autowired 
  6.     private OrderService orderService; 
  7.  
  8.     @PrintlnLog(description = "订单详情Controller"
  9.     @RequestMapping("/order"
  10.     public OrderDTO getOrder(OrderVO orderVO, String name) { 
  11.  
  12.         OrderDTO orderInfo = orderService.getOrderInfo(orderVO); 
  13.  
  14.         return orderInfo; 
  15.     } 

代码里去掉 log.info日志打印,加上 @PrintlnLog 看一下效果,清晰明了。

 

 

Demo GitHub地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-aop-unifiedlog

 

责任编辑:武晓燕 来源: 程序员内点事
相关推荐

2020-04-09 08:29:50

编程语言事件驱动

2020-10-10 09:09:21

CTOCRUD设计

2020-11-09 14:03:51

Spring BootMaven迁移

2019-11-26 10:07:10

业务开发逻辑

2022-09-26 10:01:04

SpringAOP日志

2018-03-23 05:25:18

5GWiFi网络

2019-12-02 10:34:19

Python虚拟机内存

2021-04-20 08:02:08

业务数据用户

2021-04-27 10:26:57

微软Linux桌面

2020-12-28 13:43:03

MacWindowsSurface

2022-04-06 21:50:08

区块链互联网支付

2024-02-19 09:10:46

OpenAISora功能

2014-12-01 11:20:28

Win8.1微软

2020-01-21 19:21:44

WindowsWindows 10Windows XP

2021-09-09 18:12:22

内存分段式网络

2023-11-29 09:09:27

OceanBase底层

2020-04-02 14:07:30

微信QQ转账

2018-10-06 15:38:12

2021-04-12 05:58:43

进程内核机制

2021-02-23 09:06:00

MVCC版本并发
点赞
收藏

51CTO技术栈公众号