Spring源码系列(三):通知(advice)的5种类型及转换

396 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

Advisor接口的组成

Advisor接口通常由Advice接口和PonintCut接口组成。

  • Advice:表示实际增强的逻辑入口
  • Pointcut:表示哪些类、方法需要被拦截

AbstractAspectJAdvice

image-20220417165406426

我们都知道advice(通知)有5种类型,最终通知、前置通知、后置通知、环绕通知、异常通知。

AbstractAspectJAdvice是通知类型:

  • AspectJAfterReturningAdvice -- 最终通知
  • AspectJMethodBeforeAdvice -- 前置通知
  • AspectJAfterAdvice -- 后置通知
  • AspectJAroundAdvice -- 环绕通知
  • AspectJAfterThrowingAdvice -- 异常通知

根据上方的类图可以知道AbstractAspectJAdvice下面有5个实现类,但是只有三个类是实现了MethodInterceptor接口,可以直接转换为MethodInterceptor类(子类型可以转为父类型,例如Animal接口下,有Cat、Dog的子类实现。所以Cat、Dog可以转为Animal类)。

我们为什么要将AbstractAspectJAdvice的子类转换为MethodInterceptor呢?

因为在MethodInvocation的执行过程中,需要一个个的Advice(通知来增强),这里的通知就是MethodInterceptor。

Advice

也就是说MethodInterceptor接口有三个亲生的孩子:

  • AspectJAfterAdvice -- 后置通知
  • AspectJAroundAdvice -- 环绕通知
  • AspectJAfterThrowingAdvice -- 异常通知

但是同样身为AbstractAspectJAdvice子类的AspectJAfterReturningAdvice 、AspectJMethodBeforeAdvice却不能转换为MethodInterceptor。

所以MethodInterceptor接口有两个私生子

  • AfterReturningAdviceIntercepetor -- 最终通知
  • MethodBeforeAdviceIntercepetor -- 前置通知

适配器模式

这里提供了适配器可以AspectJAfterReturningAdvice 、AspectJMethodBeforeAdvice转换为私生子。从而认祖归宗,转换为MethodInterceptor。

Advisor由Pointcut和Advice组成。

Adapter是通过适配器模式去完成Advice-->MethodInterceptor的适配过程。

来看其中的一个适配器的源码

class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
    // 为什么传递过来的是Advisor对象?我们需要的不是MethodInterceptor吗?
    // 因为根据类图可以发现,MethodInterceptor实现了Interceptor接口,Interceptor接口实现了Advice接口
    // 而Advisor由Ponitcut和Advice组成,所以这里通过advisor.getAdvice()来获取advice对象。
    // 并且强制转换为可以变成父类MethodInterceptor接口的子类。也就是AfterReturningAdviceInterceptor。
    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
        return new AfterReturningAdviceInterceptor(advice);
    }
​
}