共计 4831 个字符,预计需要花费 13 分钟才能阅读完成。
最近技术部忽然刮起一阵 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-nd…
原创不易,焚烧秀发输入内容
习惯在 VX 看技术文章,想要获取更多 Java 资源的同学,能够关注我的公众号:程序员内点事,暗号:[666]