198 lines
9.1 KiB
Markdown
198 lines
9.1 KiB
Markdown
# 精尽 Spring 源码分析 —— AOP 源码简单导读
|
||
|
||
# 1. 前置内容
|
||
|
||
Spring AOP 是基于 Spring IoC 机制来实现的,所以建议对 IoC 的源码有一定的了解。
|
||
|
||
当然,一般情况下,也是先看完 IoC 相关的源码,在来看 AOP 的源码。
|
||
|
||
# 2. 如何调试
|
||
|
||
① 调试基于 `@Aspect` 注解的 AOP 的流程
|
||
|
||
可调试 `org.springframework.aop.aspectj.autoproxy.AspectJAutoProxyCreatorTests` 这个单元测试里的方法。
|
||
|
||
# 3. 推荐资料
|
||
|
||
【必读】首先,推荐的是《Spring 源码深度解析》的 [「第7章 AOP」](https://svip.iocoder.cn/Spring/aop-simple-intro/#) 章节。
|
||
因为 Spring 静态 AOP 实际场景下,使用较少,胖友可以选择性看看。感兴趣的话,可以对 Java Instrumentation 机制做一定的了解。目前主流的链路追踪系统的 Java Agent 都是基于它来实现的。
|
||
|
||
然后,也推荐看看五月的仓颉关于 AOP 的两篇文章:
|
||
|
||
- [《【Spring源码分析】AOP源码解析(上篇)》](https://www.cnblogs.com/xrq730/p/6753160.html) ,对 Spring AOP XML 配置的方式进行源码解析。
|
||
- [《【Spring源码分析】AOP源码解析(下篇)》](https://www.cnblogs.com/xrq730/p/6757608.html) ,内容上,和《Spring 源码深度解析》的 [「第7章 AOP」](https://svip.iocoder.cn/Spring/aop-simple-intro/#) 章节,作为互为补充噶。
|
||
|
||
再然后,也非常推荐田小波关于 AOP 的四篇文章,非常**细致**,特别是对 AOP 的概念解释以及流程的拆分上:
|
||
|
||
- [《Spring AOP 源码分析系列文章导读》](https://www.tianxiaobo.com/2018/06/17/Spring-AOP-源码分析系列文章导读/)
|
||
- [《Spring AOP 源码分析 - 筛选合适的通知器》](https://www.tianxiaobo.com/2018/06/22/Spring-AOP-源码分析-拦截器链的执行过程/)
|
||
- [《Spring AOP 源码分析 - 创建代理对象》](https://www.tianxiaobo.com/2018/06/20/Spring-AOP-源码分析-创建代理对象/)
|
||
- [《Spring AOP 源码分析 - 拦截器链的执行过程》](https://www.tianxiaobo.com/2018/06/22/Spring-AOP-源码分析-拦截器链的执行过程/)
|
||
|
||
再再然后,还会灰常推荐 JavaDoop 关于 AOP 的一篇文章,看着大气:
|
||
|
||
- [《Spring AOP 源码解析》](https://www.javadoop.com/post/spring-aop-source)
|
||
|
||
最后,推荐一些和 AOP 相关的有趣的文章:
|
||
|
||
- [《Spring AOP,AspectJ, CGLIB 有点晕》](https://www.jianshu.com/p/fe8d1e8bd63e)
|
||
- [《Cglib 与 JDK 动态代理的运行性能比较》](https://www.cnblogs.com/haiq/p/4304615.html)
|
||
- [《Spring AOP 源码解析》](https://www.javadoop.com/post/spring-aop-source)
|
||
|
||
# 4. 后置内容
|
||
|
||
看完 Spring AOP 之后,当然是看 Spring Transaction 啦。
|
||
|
||
哈哈哈哈,和我们日常开发,息息相关。
|
||
|
||
# 5. 重要的类
|
||
|
||
> 老艿艿:本小节,就是艿艿简单的笔记,可以忽略。嘿嘿。后面,在找时间完善下。
|
||
|
||
核心流程如下图:
|
||
|
||
> FROM 《Spring 源码深度解析》
|
||
>
|
||
> [](http://static.iocoder.cn/images/Spring/2020-01-01/02.png)核心流程
|
||
|
||
## 5.1 aopalliance
|
||
|
||
对应 `org.aopalliance` 包。
|
||
|
||
Spring 对 AOP 联盟接口的变种。
|
||
|
||
- Advice
|
||
|
||
- Interceptor
|
||
- MethodInterceptor
|
||
|
||
- Joinpoint ,连接点接口。每个方法,都对应一个 Joinpoint 对象。
|
||
|
||
- Invocation ,调用接口。
|
||
|
||
- MethodInvocation ,方法调用接口。
|
||
|
||
- ProxyMethodInvocation ,代理方法调用接口。在根目录的包里。
|
||
|
||
- ReflectiveMethodInvocation ,反射方法调用实现类。在
|
||
|
||
|
||
|
||
```
|
||
framework
|
||
```
|
||
|
||
|
||
|
||
包里。
|
||
|
||
- CglibMethodInvocation ,基于 CGLIB 方法调用实现类。在 `framework` 包里。
|
||
|
||
- Advice ,定义的横切逻辑。在如下几个时机,可以进行执行:
|
||
|
||
- Before :在目标方便调用前执行通知。
|
||
- After :在目标方法完成后执行通知。
|
||
- After Returning : 在目标方法执行成功后,调用通知。
|
||
- After Throwing :在目标方法抛出异常后,执行通知。
|
||
- Around :在目标方法调用前后均可执行自定义逻。
|
||
|
||
## 5.2 config
|
||
|
||
对应 `org.springframework.aop.config` 包。
|
||
|
||
AopNamespaceHandler ,对 `<aop:/>` 命名空间的处理器。
|
||
|
||
- AspectJAutoProxyBeanDefinitionParser ,将 `<aop:aspectj-autoproxy/>` 标签,解析成 BeanDefinition 的解析器。
|
||
- ScopedProxyBeanDefinitionDecorator
|
||
- ConfigBeanDefinitionParser
|
||
- SpringConfiguredBeanDefinitionParser
|
||
|
||
## 5.3 framework
|
||
|
||
对应 `org.springframework.aop.framework` 包。
|
||
|
||
AutoProxyCreator 整体类图如下:
|
||
|
||
[](http://static.iocoder.cn/images/Spring/2020-01-01/01.png)AutoProxyCreator 类图
|
||
|
||
- AbstractAutoProxyCreator ,自动代理构造器抽象类。
|
||
- `#wrapIfNecessary(Object bean, String beanName, Object cacheKey)` 方法,如果需要,将制定 Bean 对象包装成 **Proxy 代理**对象。
|
||
- `#createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource)` 方法,创建 **Proxy 代理**对象。
|
||
- AbstractAdvisorAutoProxyCreator ,基于 Advisor 的 自动代理构造器抽象类。
|
||
- `#findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName)` 方法,获得 Bean 对象**可使用**的 Advisor 集合,是从 `candidateAdvisors` 参数中筛选出来的。
|
||
- `#getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource)` 方法,获得 Bean 对象**可使用**的 Advisor 集合。
|
||
- AnnotationAwareAspectJAutoProxyCreator ,支持 AOP 注解的,基于 AspectJ 的代理自动构造器。
|
||
- ProxyFactory ,创建 Proxy 的工厂类。
|
||
- DefaultAopProxyFactory ,默认 ProxyFactory 实现类。
|
||
- AopProxy ,AOP 代理接口,创建对应的代理对象。
|
||
- 它有两个子类:
|
||
- JdkDynamicAopProxy ,基于 JDK 的 AOP 代理实现类。
|
||
- `#invoke(Object proxy, Method method, Object[] args)` 方法,实现 InvocationHandler 的接口方法,执行代理的调用。【重要】
|
||
- ObjenesisCglibAopProxy ,基于 CGLIB 的 AOP 的代理实现类。
|
||
- `#getProxy(ClassLoader classLoader)` 方法,创建对应的代理对象。
|
||
- AopContext ,AOP 上下文,基于 ThreadLocal 实现。
|
||
- AdvisorChainFactory ,Advisor 调用链工厂接口,用于获取每个方法调用时的调用链。
|
||
- `#getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass)` 方法,获得指定方法拦截的拦截器链。
|
||
- DefaultAdvisorChainFactory ,默认实现类。
|
||
- ProxyMethodInvocation ,代理方法调用接口。
|
||
- ReflectiveMethodInvocation ,基于反射的方式,代理方法调用实现类。
|
||
- `#proceed()` 方法,执行方法。基于递归的方式,调用每个拦截器链中的拦截器,最后调用真正的方法。
|
||
- `#invokeJoinpoint()` 方法,执行真正的方法,即切点的方法。
|
||
- CglibMethodInvocation ,基于 CGLIB 的方式,进一步优化调用的实现类。
|
||
- 各种情况下,调用:
|
||
- MethodBeforeAdviceInterceptor
|
||
- AfterReturningAdviceInterceptor
|
||
- AspectJAroundAdvice
|
||
- AspectJAfterAdvice
|
||
- AspectJAfterThrowingAdvice
|
||
- ThrowsAdviceInterceptor
|
||
|
||
## 5.4 aspectj
|
||
|
||
对应 `org.springframework.aop.aspectj` 包。
|
||
|
||
- ReflectiveAspectJAdvisorFactory
|
||
- BeanFactoryAspectJAdvisorsBuilder
|
||
- `#buildAspectJAdvisors()` 方法,构建**所有** @Aspect 注解类的增强方法对应的 Advisor 对象。
|
||
- AnnotationAwareAspectJAutoProxyCreator
|
||
- `#findCandidateAdvisors()` 方法,获得**所有**增强方法对应的 Advisor 对象。
|
||
- InstantiationModelAwarePointcutAdvisorImpl
|
||
- AbstractAspectJAdvice ,基于 AspectJ ,实现 Advice 接口的 Advice 抽象类。
|
||
- 有如下几个子类:
|
||
- AspectJAroundAdvice
|
||
- AspectJMethodBeforeAdvice
|
||
- AspectJAfterAdvice
|
||
- AspectJAfterReturningAdvice
|
||
- AspectJAfterThrowingAdvice
|
||
- 通过 `ReflectiveAspectJAdvisorFactory#getAdvice(...)` 方法,构建 AbstractAspectJAdvice 对象。
|
||
- 通过 `#invokeAdviceMethodWithGivenArgs(Object[] args)` 方法,执行增强 Advice 的方法。【重要】
|
||
|
||
## 5.5 interceptor
|
||
|
||
对应 `org.springframework.aop.interceptor` 包。
|
||
|
||
- ExposeInvocationInterceptor
|
||
|
||
## 5.6 scope
|
||
|
||
对应 `org.springframework.aop.scope` 包。
|
||
|
||
## 5.7 support
|
||
|
||
对应 `org.springframework.aop.support` 包。
|
||
|
||
## 5.8 target
|
||
|
||
对应 `org.springframework.aop.target` 包。
|
||
|
||
提供多种 TargetSource 的实现类,而 TargetSource 可以理解成 Target 的数据源,可以根据每次方法调用,返回相同或不同的 Target 对象。可以选择性看看,感兴趣的胖友,可以看看 [《spring-aop组件详解——TargetSource目标源》](https://my.oschina.net/lixin91/blog/688188) 。
|
||
|
||
## 5.9 根目录
|
||
|
||
对应 `org.springframework.aop` 包的根目录。
|
||
|
||
- Pointcut ,切点接口,用于选择连接点。
|
||
- 其定义了两个接口方法,分别返回:
|
||
- ClassFilter ,匹配哪些类。
|
||
- MethodMatcher ,匹配哪些方法。
|
||
- AspectJExpressionPointcut ,AspectJ 的切点表达式。 |