当前位置: 首页 > 科技观察

被迫再次优化代码,这次把进出日志给干掉了

时间:2023-03-22 12:41:35 科技观察

转载本文请联系程序员内店师公众号。最近技术部突然刮起了review代码的小风,代码一个一个的review。按理说,这应该是一件非常好的事情。让别人指出自己代码中的不足,查漏补缺,对提高自己的编码能力有很大的帮助。帮助很大,毕竟自己复习的时候很容易“陶醉”在自己写的代码里。然而codereview的详细程度令人发指,逐行分析简直就是培训班。不夸张的说,如果我村只有四个县重点小学毕业的硕士,听了一个月,保证可以开始开发了,666~现在这气氛群来了,我们得行动起来了,不然哪天review了我的代码,让人指指点点,感觉有点不舒服。与其被动优化代码,不如主动出击~选择优化代码的方向,方法入参和返回结果日志首当其冲。每个方法都会有这两个日志,很多冗余代码,打印格式也是五花八门,很乱。publicOrderDTOgetOrder(OrderVOorderVO,Stringname){log.info("订单详情入口:orderVO={},name={}",JSON.toJSONString(orderVO),name);OrderDTOorderInfo=orderService.getOrderInfo(orderVO);log.info("Orderdetailsresult:orderInfo={}",JSON.toJSONString(orderInfo));returnorderInfo;}下面我们使用AOP实现请求方法的入参,并统一打印返回结果日志,避免日志打印混乱格式化并减少业务代码数量。1.自定义注解自定义切面注解@PrintlnLog用于输出日志,注解权限@Target({ElementType.METHOD})限制只能在方法上使用。注解中只有一个参数描述,用于自定义方法输出日志的描述。@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})@Documentedpublic@interfacePrintlnLog{/***自定义日志描述信息copy**@return*/Stringdescription()default"";}2.分段连接下一步,编写@PrintlnLog注解对应的切面实现,doBefore()中输出方法的自定义描述,输入参数,请求方法,请求url,调用方法位置等信息,doAround()中打印方法返回结果。注意:如果要指定切面执行的环境,可以使用@Profile注解只打印某个环境的日志。@Slf4j@Aspect@Component//@Profile({"dev"})//只打印某个环境的日志publicclassLogAspect{privatestaticfinalStringLINE_SEPARATOR=System.lineSeparator();/***使用自定义的@PrintlnLog注解作为切面入口*/@Pointcut("@annotation(com.chengxy.unifiedlog.config.PrintlnLog)")publicvoidPrintlnLog(){}/***@paramjoinPoint*@authorfu*@description段方法入口日志打印*@date2020/7/1510:30*/@Before("PrintlnLog()")publicvoiddoBefore(JoinPointjoinPoint)throwsThrowable{ServletRequestAttributesattributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();HttpServletRequestrequest=attributes.getRequest();StringmethodDetailDescription=this.getAspectMethodLogDescJP(joinPoint);日志。信息(“----------------------------开始-----------------------");/***打印自定义方法描述*/log.info("MethoddetailDescription:{}",methodDetailDescription);/***打印请求输入参数*/log.info("RequestArgs:{}",JSON.toJSONString(joinPoint.getArgs()));/***打印请求方法*/log.info("Requestmethod:{}",request.getMethod());/***打印请求url*/log.info("RequestURL:{}",request.getRequestURL().toString());/***打印调用方法全路径和执行方法*/log.info("RequestClassandMethod:{}.{}",joinPoint.getSignature().getDeclaringTypeName(),joinPoint.getSignature().getName());}/***@paramprocedingJoinPoint*@authorxiaofu*@description方面方法返回结果日志打印*@date2020/7/1510:32*/@Around("PrintlnLog()")publicObjectdoAround(ProceedingJoinPointproceedingJoinPoint)throwsThrowable{StringaspectMethodLogDescPJ=getAspectMethodLogDescPJ(proceedingJorrinTimeisPoint);longstartTime=illM();Objectresult=proceedingJoinPoint.proceed();/***输出结果*/log.info("{},Responseresult:{}",aspectMethodLogDescPJ,JSON.toJSONString(result));/***方法执行消费时*/log.info("TimeConsuming:{}ms",System.currentTimeMillis()-startTime);returnresult;}/***@authorxiaofu*@descriptionsection方法执行后执行*@date2020/7/1510:31*/@After("PrintlnLog()")publicvoiddoAfter(JoinPointjoinPoint)throwsThrowable{log.info("--------------------------------结束--------------------------"+LINE_SEPARATOR);}/***@paramjoinPoint*@authorxiaofu*@description@PrintlnLogAnnotation方法详细信息*@date2020/7/1510:34*/publicStringgetAspectMethodLogDescJP(JoinPointjoinPoint)throwsException{StringtargetName=joinPoint.getTarget().getClass().getName();StringmethodName=joinPoint.getSignature().getName();Object[]arguments=joinPoint.getArgs();returngetAspectMethodLogDesc(targetName,methodName,arguments);}/***@paramproceedingJoinPoint*@authorxiaofu*@description@PrintlnLog注解效果aspect方法详解*@date2020/7/1510:34*/publicStringgetAspectMethodLogDescPJ(ProceedingJoinPointpthproceedingsJoince{StringtargetName=proceedingJoinPoint.getTarget().getClass().getName();StringmethodName=proceedingJoinPoint.getSignature().getName();Object[]arguments=proceedingJoinPoint.getArgs();returngetAspectMethodLogDesc(targetName,methodName,arguments);}/***@param目标名称*@parammethodName*@paramarguments*@authorxiaofu*@description自定义注解参数*@date2020/7/1511:51*/publicStringgetAspectMethodLogDesc(StringtargetName,StringmethodName,Object[]arguments)throwsException{ClasstargetClass=Class.forName(targetName);Method[]methods=targetClass.getMethods();StringBuilderdescription=newStringBuilder("");for(Methodmethod:methods){if(method.getName().equals(methodName)){Class[]clazzs=method.getParameterTypes();if(clazzs.length==arguments.length){description.append(method.getAnnotation(PrintlnLog.class).description());break;}}}returndescription.toString();}}三、应用我们需要打印输入参数和返回结果日志的方法,添加@PrintlnLog注解,添加自定义方法说明@RestController@RequestMappingpublicclassOrderController{@AutowiredprivateOrderServiceorderService;@PrintlnLog(description="OrderDetailsController")@RequestMapping("/order")publicOrderDTOgetOrder(OrderVOorderVO,Stringname){OrderDTOorderInfo=orderService.getOrderInfo(orderVO);returnorderInfo被移除;}}代码log.info日志打印,加上@PrintlnLog看效果,清晰明了。DemoGitHub地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-aop-unifiedlog