【Spring源码三千问】Advice、Advisor、Advised都是什么接口?

前言

在看 Spring AOP 的源码时,经常可以看到 Advice、Advisor、Advised 等接口,它们长的很像,初次见面时,看着都有些让人犯糊涂,但是却拥有着不同的功能。
理解这些接口的作用,能够让我们更好的理解 Spring AOP。

版本约定

Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)

正文

  • Advice: org.aopalliance.aop.Advice
    “通知”,表示 Aspect 在特定的 Join point 采取的操作。包括 “around”, “before” and “after 等

  • Pointcut: org.springframework.aop.Pointcut
    “切点”,它是用来匹配连接点 Join point 的,可以说"Pointcut"表示的是"Join point"的集合。

  • Advisor: org.springframework.aop.Advisor
    “通知者”,它持有 Advice,是 Spring AOP 的一个基础接口。

  • Advised: org.springframework.aop.framework.Advised
    AOP 代理工厂配置类接口。提供了操作和管理 Advice 和 Advisor 的能力。

下面我们通过类的继续关系图的方式,来从一个比较高的视角来观察一下 Advice、Advisor、Advised 接口。

通过类图,能让我们有一个全面的了解,而不是钻进某一个类里面,只见树木,不见森林!

Advice、Advisor、Advised 类图

AdviceAdvisorUML

  1. Advisor 可以获取到 Advice。
  2. PointcutAdvisor 可以获取到 Pointcut 和 Advice。
    Pointcut 可以匹配 join point,Advice 是具体的通知,所以,PointcutAdvisor 是一个功能完善接口。
  3. Advised 是 AOP 代理工厂配置类接口,它可以操作和管理 Advice 和 Advisor,它的实现类有 ProxyFactoryAspectJProxyFactory,用于生成AOP 代理类。

AdviceAdvisorAdvised

Advice

Advice

Advice 大体上分为了三类:BeforeAdvice、MethodInterceptor、AfterAdvice

可以看出,MethodInterceptor 是功能最强大的,它能够处理 BeforeAdvice、AroundAdvice、AfterAdvice、ThrowsAdvice、@Valid方法参数校验、@Async异步等

MethodInterceptor

MethodInterceptor

MethodInterceptor 是功能最强大的,它能够处理 BeforAdvice、AroundAdvice、AfterAdvice、ThrowsAdvice、限流、@Valid方法参数校验、@Async异步、事务等
MethodInterceptor 除了可以处理 Advice 类的通知拦截外,还是一个比较能用的方法拦截接口。

例如:给接口 FooService 添加一个方法拦截器

FooService fooService = ProxyFactory.getProxy(FooService.class, new MyInterceptor());

在执行 FooService 的任意方法时,都会经过 MyInterceptor 的处理。

ProxyFactory#getProxy(Class, Interceptor)
它可以为给定接口和 Interceptor 拦截器创建代理类。
这个方法是一个静态方法,可以给单个 Interceptor 拦截器创建代理,这个拦截器自己处理所有的调用,而不是委托给目标(如远程调用代理)。

public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
    return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();
}

Advisor

Advisor

Advisor 大体分为了三类:PointcutAdvisor、IntroductionAdvisor、PrototypePlaceholderAdvisor
其中,用到的最多的就是 PointcutAdvisor,它涵盖了绝大部分的 Advisor。

PointcutAdvisor

PointcutAdvisor 是一个功能完善接口,也是 Spring AOP 中使用最多的,它涵盖了绝大部分的 Advisor。

通过 PointcutAdvisor 可以获取到 Pointcut 和 Advice。Pointcut 可以完成 join point 的匹配,而 Advice 就是在 join point 上具体要执行的"通知"。

Advised

Advised
proxyFactory

Advised 是 AOP 代理工厂配置类接口。

它的实现类有:ProxyFactory、AspectJProxyFactory、ProxyFactoryBean。
Advised 提供了操作和管理 Advice 和 Advisor 的能力,所以,ProxyFactory 实现 Advised 之后,就可以方便的获取和操作 Advice、Advisor,从而创建 AOP 代理类了。

Advised、ProxyConfig、AdvisedSupport 都是跟 Spring AOP 代理配置相关的接口和类,它们可以统一 Spring AOP 的代理配置。

Spring AOP 代理类可以转换为 Advised 类型

Spring AOP 在产生代理类时,会调用 AopProxyUtils#completeProxiedInterfaces(),将 AdvisedSpringProxy 添加为代理类实现的接口。
这样,所有的 Spring AOP 代理类都实现了 Advised 接口,所以,Spring AOP 代理类可以转换为 Advised 类型

既然 Spring AOP 代理类可以转换为 Advised 类型,那么代理类就可以操作 Advice 和 Advisor 了。
我们可以测试一下:

@RestController
@SpringBootApplication
//@EnableAspectJAutoProxy
public class AopApplication {
    @Resource
    private FoService foService;
    @Resource
    private FoService foService2;
    @Resource
    private XoService xoService;

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(AopApplication.class);
        app.setBannerMode(Banner.Mode.OFF);
        app.run(args);
    }

    @GetMapping("/status")
    public String status() {
        if (foService instanceof Advised) {
            // 动态添加 Advice 
            ((Advised) foService).addAdvice(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println("动态添加:before execute:" + method);
                }
            });
        }
        foService.doBiz();

        System.out.println(">>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<");
        // 测试对相同 bean 和不同 bean 的影响
        foService2.doBiz();
        xoService.doBiz();
        return ObjectUtils.identityToString(foService);
    }
}

输出:

before...public java.lang.String com.kvn.aop.advised.FoService.doBiz()
动态添加:before execute:public java.lang.String com.kvn.aop.advised.FoService.doBiz()
FoooooooService#doBiz
finally...public java.lang.String com.kvn.aop.advised.FoService.doBiz()
>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<
before...public java.lang.String com.kvn.aop.advised.FoService.doBiz()
动态添加:before execute:public java.lang.String com.kvn.aop.advised.FoService.doBiz()
FoooooooService#doBiz
finally...public java.lang.String com.kvn.aop.advised.FoService.doBiz()
before...public java.lang.String com.kvn.aop.advised.XoService.doBiz()
XxxxxoService#doBiz
finally...public java.lang.String com.kvn.aop.advised.XoService.doBiz()

可以看出:
Spring AOP 代理类都可以转换为 Advised 接口,并可以使用它来操作 Advice 和 Advisor。
如果更改了 FooService 的 Advice 后,对所有注入 FooService 的地方都有影响,但是不会影响到其他类型的 bean。

原因分析:
Spring AOP 代理类的 Advice、Advisor 等 ProxyConfig 配置是保存在 ProxyFactory 中的。
由于 Spring AOP 代理对象每次都是通过 new ProxyFactory 来创建的,对于不同的 proxy bean 而言,ProxyConfig 代理配置都是各自持有,所以,对 bean 对应的 Advised 的操作只会体现在这一个类型的 bean 上面。
不同类型的 bean 之间是互不影响的。测试例子中也证明了这一点

关于 Spring AOP 产生代理的过程可以点击传送门: 如何为 Pointcut 匹配的类生成动态代理类

小结

Advice、Advisor、Advised 都是 Spring AOP 相关的基本接口,理解这些接口的作用,对于更好的理解 Spring AOP 有很大的好处:

  • Advice: org.aopalliance.aop.Advice
    “通知”,表示 Aspect 在特定的 Join point 采取的操作。包括 “around”, “before” and “after 等
    Advice 大体上分为了三类:BeforeAdvice、MethodInterceptor、AfterAdvice
    MethodInterceptor 是功能最强大的,是一个通用的方法拦截接口,它能够处理 BeforeAdvice、AroundAdvice、AfterAdvice、ThrowsAdvice、@Valid方法参数校验、@Async异步等

  • Advisor: org.springframework.aop.Advisor
    “通知者”,它持有 Advice,是 Spring AOP 的一个基础接口。
    它的子接口 PointcutAdvisor 是一个功能完善接口,它涵盖了绝大部分的 Advisor。

  • Advised: org.springframework.aop.framework.Advised
    AOP 代理工厂配置类接口。提供了操作和管理 Advice 和 Advisor 的能力。
    它的实现类 ProxyFactory 是 Spring AOP 主要用于创建 AOP 代理类的核心类。


如果本文对你有所帮助,欢迎点赞收藏!

源码测试工程下载:
老王读Spring IoC源码分析&测试代码下载
老王读Spring AOP源码分析&测试代码下载

公众号后台回复:下载IoC 或者 下载AOP 可以免费下载源码测试工程…

阅读更多文章,请关注公众号: 老王学源码
gzh


系列博文:
【老王读Spring AOP-0】SpringAop引入&&AOP概念、术语介绍
【老王读Spring AOP-1】Pointcut如何匹配到 join point
【老王读Spring AOP-2】如何为 Pointcut 匹配的类生成动态代理类
【老王读Spring AOP-3】Spring AOP 执行 Pointcut 对应的 Advice 的过程
【老王读Spring AOP-4】Spring AOP 与Spring IoC 结合的过程 && ProxyFactory 解析
【老王读Spring AOP-5】@Transactional产生AOP代理的原理
【老王读Spring AOP-6】@Async产生AOP代理的原理
【Spring 源码阅读】Spring IoC、AOP 原理小总结

相关阅读:
【Spring源码三千问】Spring动态代理:什么时候使用的 cglib,什么时候使用的是 jdk proxy?
【Spring源码三千问】Advice、Advisor、Advised都是什么接口?
【Spring源码三千问】没有AspectJ,Spring中如何使用SpringAOP、@Transactional?
【Spring源码三千问】Spring AOP 中 AbstractAdvisorAutoProxyCreator、AbstractAdvisingBeanPostProcessor的区别
【Spring 源码三千问】同样是AOP代理bean,为什么@Async标记的bean循环依赖时会报错?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老王学源码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值