自定义日志标签YfLog
日志注解:以日志自定义注解+AOP实现
####1、引入AOP Maven依赖
<!--springBoot 的aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
####2、创建自定义注解 YfLog
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface YfLog {
}
####3、创建切面类 YfLogAspect
使用@Aspect注解将一个java类定义为切面类
使用@Pointcut定义一个切入点,可以是一个规则表达式,
根据需要在切入点不同位置的切入内容
@Before : 在切入点开始处切入内容
@After : 在切入点结尾处切入内容
@Around : 在切入点前后切入内容,并控制何时执行切入点自身的内容
@AfterReturning : 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
@AfterThrowing : 用来处理当切入内容部分抛出异常之后的处理逻辑
切面类YfAspect如下:
@Aspect
@Component
@Order(-99) // 控制多个Aspect的执行顺序,越小越先执行
public class YfLogAspect {
private static final Logger LOGGER= LoggerFactory.getLogger(YfLogAspect.class);
@Pointcut("execution(* com.yf.custom..*.*(..))")
private void pointcut(){ }
@Before("pointcut() && @annotation(YfLog)")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 打印日志
LOGGER.info("before : url=" + request.getRequestURL().toString());
}
/**
* ProceedingJoinPoint is only supported for around advice
* 环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的。
环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。
Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法
*/
@Around(value = "pointcut() && @annotation(yfLog)")
public Object before(ProceedingJoinPoint point, YfLog yfLog){
Class clazz = point.getTarget().getClass();
String method =point.getSignature().getName();
//入口参数
StringBuilder logSB=new StringBuilder();
Object[] args = point.getArgs();
int i = args.length;
for (Object arg : args) {
logSB.append(arg.toString() + ",");
}
LOGGER.info("around start: class=" + clazz + ",method=" + method +",params="+logSB.toString());
try {
//执行程序
Object object=point.proceed();
LOGGER.info("around over: result="+object.toString());
return object;
} catch (Throwable throwable) {
throwable.printStackTrace();
return throwable.getMessage();
}
}
}
####4、测试日志打印
只有使用@YfLog的方法,才执行切面内定义的逻辑
访问 http://localhost:8080/testLog?a=1 @YfLog切面触发
访问 http://localhost:8080/testLog2?a=1 无切面内容触发
另外,@Before和@Around的执行顺序,由日志表明,先执行@Around的开头,待真正执行方法时,才触发了@Before方法