基本思想
- 凡在目标实例上或在目标实例方法(非静态方法)上标注自定义注解
@AutoLog,其方法执行时将触发AOP操作; @AutoLog只有一个参数,用来控制是否打印该方法的参数和返回结果的json字符串,默认不打印,通过@AutoLog(debug= true)开启- 通过AOP拦截方法并打印日志
代码
package com.yan.mssm.aop
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoLog {
boolean debug() default false
}
package com.yan.mssm.aop;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Optional;
@Component
@Aspect
public class AutoLogAspectJ {
private static final String LOG_FORMAT = "[AOP-LOG]->Method {}: {}";
private static final String BEGIN = "begin";
private static final String END = "end";
private static final String PARAMS = "params";
private static final String RESULT = "result";
private static Logger LOGGER;
private static String toJsonString(Object object) {
ObjectMapper objectMapper = new ObjectMapper();
String result = null;
try {
result = objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
LOGGER.error(e.getMessage());
}
return result;
}
@Around(value = "@within(com.yan.mssm.aop.AutoLog) || @annotation(com.yan.mssm.aop.AutoLog)")
public Object test(ProceedingJoinPoint point) throws Throwable {
Class targetClass = point.getTarget().getClass();
LOGGER = LoggerFactory.getLogger(targetClass);
Signature signature = point.getSignature();
String methodSignature = signature.toString();
boolean debug = isDebug(targetClass, AutoLog.class, signature.toLongString());
LOGGER.info(LOG_FORMAT, BEGIN, methodSignature);
printParams(point, LOGGER, debug);
Object result = point.proceed();
printResult(LOGGER, debug, result);
LOGGER.info(LOG_FORMAT, END, methodSignature);
return result;
}
private void printResult(Logger logger, boolean debug, Object result) {
if (debug) {
Optional.ofNullable(result)
.ifPresent(o -> logger.info(LOG_FORMAT, RESULT, o));
}
}
private void printParams(ProceedingJoinPoint point, Logger logger, boolean debug) {
if (debug) {
Object[] args = point.getArgs();
if (args.length == 0) {
return;
}
logger.info(LOG_FORMAT, PARAMS, toJsonString(args));
}
}
private boolean isDebug(Class targetClass, Class<AutoLog> autoLogClass, String longMethodSignature) {
return targetClass.isAnnotationPresent(autoLogClass)
&& ((AutoLog) targetClass.getDeclaredAnnotation(autoLogClass)).debug()
|| Arrays.stream(targetClass.getDeclaredMethods())
.filter(method -> method.toString().equals(longMethodSignature) && method.isAnnotationPresent(autoLogClass))
.anyMatch(method -> method.getAnnotation(autoLogClass).debug());
}
}