日志自定义注解(AOP实现)

自定义日志标签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方法

扫描二维码关注公众号,回复: 11616621 查看本文章

猜你喜欢

转载自blog.csdn.net/weikzhao0521/article/details/103508863