1. 程式人生 > >spring boot使用aop攔截Controller和Service以方便除錯

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有一個按鈕
在這裡插入圖片描述
每次寫完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檔案應該是等價的