spring boot使用aop拦截Controller和Service以方便调试

调试的时候,经常需要看每个函数的输入输出,以前每次都是System.out.println输出,调试完后还要删掉,要是每次都能自己输出函数的输入输出就好了。
在网上找了一通,结合《Spring 实战》写了一个自己用的切面

  • BaseAspect
public abstract class BaseAspect {
    protected Object process(ProceedingJoinPoint pjp, StringBuilder sb) throws Throwable {
        //获取连接点目标类名
        String targetName = pjp.getTarget().getClass().getName();
        //获取连接点签名的方法名
        String methodName = pjp.getSignature().getName();
        //获取连接点参数
        Object[] args = pjp.getArgs();
        //根据连接点类的名字获取指定类
        Class targetClass = Class.forName(targetName);
        //获取类里面的方法
        Method[] methods = targetClass.getMethods();
        Object object = pjp.proceed();
        sb.append(targetClass.getCanonicalName())
                .append(methodName)
                .append(JSON.toJSONString(args))
                .append(object);
        return object;
    }
}
  • ControllerDebugAspect
/**
 * Controller调试用切面,可以快速了解输入输出是
 */
@Aspect
@Component
@Slf4j
public class ControllerDebugAspect extends BaseAspect{
    @Pointcut("execution(* api.*.controller.*.*(..)) || execution(* api.controller.*.*(..))")
    public void Pointcut() {
    }
    @Around("Pointcut()")
    public Object Around(ProceedingJoinPoint pjp) throws Throwable {
        StringBuilder sb = new StringBuilder();
        Object object = process(pjp, sb);
        logger.debug(sb.toString());
        return object;
    }
}

  • ServiceDebugAspect
@Aspect
@Component
@Slf4j
public class ServiceDebugAspect extends BaseAspect{
    //    @Pointcut("@annotation(org.springframework.web.bind.annotation.RestController) || @annotation(org.springframework.stereotype.Service)")
    @Pointcut("execution(* api.*.service.impl.*.*(..)) || execution(* api.service.impl.*.*(..))")
    public void Pointcut() {
    }
    @Around("Pointcut()")
    public Object Around(ProceedingJoinPoint pjp) throws Throwable {
        StringBuilder sb = new StringBuilder();
        Object object = process(pjp, sb);
        logger.debug(sb.toString());
        return object;
    }
}

后面两个其实是一样的。
在调试的时候,IDEA有一个按钮
spring boot使用aop拦截Controller和Service以方便调试_第1张图片
每次写完Pointcut表达式,按一下可以知道有哪些方法会生效
除了代码,还有两个地方
一个是application.properties文件


#aop
spring.aop.proxy-target-class=true
spring.aop.auto=true

一个是在@SpringBootApplication所在的类上写注解

@EnableAspectJAutoProxy(exposeProxy=true)

后来测了一下,去掉注解也是可以的
看了一下注解源码

public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

使用注解和写application.properties文件应该是等价的

你可能感兴趣的:(spring boot使用aop拦截Controller和Service以方便调试)