Bootstrap

Spring AOP 自定义Advisor

我们在使用AOP时通常都是直接使用@Before、@After、@Around、@AfterThrowing、@AfterReturning等注解来拦截方法的,其实Spring还有另外一种方式来实现AOP,那就是创建Advisor

Advisor(顾问)的组成:Advisor内部包含了PointCut(切点)和Advice(通知),PointCut表名要匹配哪些类的哪些方法,Advice表明要植入的代码。

其实我们编写的@Before等注解最终还是会被解析为Advis

注解实现类
@AroundAspectJAroundAdvice
@BeforeAspectJMethodBeforeAdvice
@AfterAspectJAfterAdvice
@AfterReturingAspectJAfterReturingAdvice
@AfterThrowingAspectJAfterThrowingAdvice

1. 编写PointCut

PointCut表明我们需要代理哪些类的哪些方法。

/**
 * 切点:包含了 MethodMatcher(方法匹配器)
 */
public class LogPrintPointCut implements Pointcut {

    /**
     * 指明要拦截哪些类
     */
    @Override
    public ClassFilter getClassFilter() {
        return new ClassFilter() {
            @Override
            public boolean matches(Class<?> clazz) {
                //拦截所有类
                return true;
            }
        };
    }

    /**
     * 指明要拦截哪些方法
     */
    @Override
    public MethodMatcher getMethodMatcher() {
        return new MethodMatcher() {
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                //拦截加了LogPrint注解的所有方法
                return Objects.nonNull(method.getAnnotation(LogPrint.class));
            }

            //后面2个方法不会用到,返回false即可
            @Override
            public boolean isRuntime() {
                return false;
            }
            @Override
            public boolean matches(Method method, Class<?> targetClass, Object... args) {
                return false;
            }
        };
    }
}

2. 编写Advice

Advice标明要执行的操作

/**
 * 自定义环绕通知
 */
@Slf4j
public class LogPrintAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //执行方法
        Object proceed = invocation.proceed();

        Map<String,Object> parameterMap = new HashMap<>();
        List<Parameter> parameterList = Arrays.asList(invocation.getMethod().getParameters());
        for (int i = 0; i < parameterList.size(); i++) {
            parameterMap.put(parameterList.get(i).getName(),invocation.getArguments()[i]);
        }
        log.info("环绕通知-{}执行成功,参数{},返回值{}",invocation.getMethod().getName(), JSONUtil.toJsonStr(parameterMap),proceed);
        return proceed;
    }

}

3. 注入Advisor

往Spring容器内放入Advisor,Spring即可生成代理类

/**
 * Advisor(顾问) 包含了Advice(通知)和PointCut(切点)
 */
@Component
public class MyAdvisor implements PointcutAdvisor {
    @Override
    public Pointcut getPointcut() {
        return new LogPrintPointCut();
    }

    @Override
    public Advice getAdvice() {
        return new LogPrintAdvice();
    }
}
;