#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

业无高卑志当坚,男儿有求安得闲?这篇文章主要讲述#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口?相关的知识,希望能为你提供帮助。
@TOC
前言在看 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 类图
#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

文章图片

  1. Advisor 可以获取到 Advice。
  2. PointcutAdvisor 可以获取到 Pointcut 和 Advice。
    Pointcut 可以匹配 join point,Advice 是具体的通知,所以,PointcutAdvisor 是一个功能完善接口。
  3. Advised 是 AOP 代理工厂配置类接口,它可以操作和管理 Advice 和 Advisor,它的实现类有 ProxyFactoryAspectJProxyFactory,用于生成AOP 代理类。
#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

文章图片

Advice
#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

文章图片

Advice 大体上分为了三类:BeforeAdvice、MethodInterceptor、AfterAdvice
可以看出,MethodInterceptor 是功能最强大的,它能够处理 BeforeAdvice、AroundAdvice、AfterAdvice、ThrowsAdvice、@Valid方法参数校验、@Async异步等
MethodInterceptor
#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

文章图片

MethodInterceptor 是功能最强大的,它能够处理 BeforAdvice、AroundAdvice、AfterAdvice、ThrowsAdvice、限流、@Valid方法参数校验、@Async异步、事务等
MethodInterceptor 除了可以处理 Advice 类的通知拦截外,还是一个比较能用的方法拦截接口。
例如:给接口 FooService 添加一个方法拦截器
FooService fooService = ProxyFactory.getProxy(FooService.class, new MyInterceptor());

在执行 FooService 的任意方法时,都会经过 MyInterceptor 的处理。
public static < T> T getProxy(Class< T> proxyInterface, Interceptor interceptor) return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();

Advisor
#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

文章图片

【#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()】Advisor 大体分为了三类:PointcutAdvisor、IntroductionAdvisor、PrototypePlaceholderAdvisor
其中,用到的最多的就是 PointcutAdvisor,它涵盖了绝大部分的 Advisor。
PointcutAdvisor
PointcutAdvisor 是一个功能完善接口,也是 Spring AOP 中使用最多的,它涵盖了绝大部分的 Advisor。
通过 PointcutAdvisor 可以获取到 Pointcut 和 Advice。Pointcut 可以完成 join point 的匹配,而 Advice 就是在 join point 上具体要执行的" 通知" 。
Advised
#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

文章图片

#yyds干货盘点#Spring源码三千问AdviceAdvisorAdvised都是什么接口()

文章图片

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 之间是互不影响的。测试例子中也证明了这一点
小结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 源码方面的问题欢迎一起交流,备注:51cto (vx: Kevin-Wang001)
博主好课推荐:
课程 地址
Dubbo源码解读——通向高手之路 https://edu.51cto.com/course/23382.html
正则表达式基础与提升 https://edu.51cto.com/course/16391.html

    推荐阅读