## 前言
在[Spring AOP - 注解方式使用介绍(长文详解)](https://juejin.im/post/5dbffe37f265da4d17138615)中,作者介绍了Spring AOP 注解方式的使用方式。算是给咱们的Spring AOP 源码分析开了个头,做了一点知识点的铺垫。
在开始学习Spring AOP的源码之前,如果你还没有学习过Spring IoC的源码,最好先去学习下Spring IoC。
- [Spring IoC - Spring IoC 的设计](/archives/Spring%20IoC%20-%20Spring%20IoC%20%E7%9A%84%E8%AE%BE%E8%AE%A1)
- [Spring IoC - IoC 容器初始化 源码解析](/archives/Spring%20IoC%20%20-%20IoC%20%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB)
- [Spring IoC - 依赖注入 源码解析](/archives/Spring%20IoC%20-%20%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90)
Spring AOP 只作用于Spring Bean 的特性说明了Spring AOP和Spring IOC 的关系,AOP 依赖于 IOC 容器来管理,后面的源码分析也会涉及到Spring IoC 的源码内容。
下面,假设你已经学习过Spring IoC 的相关内容和Spring AOP的相关使用,让我们开始吧。
**本文耗费了作者大量心力,希望能对你有所帮助。**

我们前面一直说的Spring AOP源码解析,源码这么多,我们真正关注的内容是什么?
Spring AOP的功能是什么?从使用上直白的说,就是根据我们的配置来生成代理类,拦截指定的方法,将指定的advice织入。
我们应该关注的内容总结下来就是:
- **Spring AOP 的触发时机是什么时候?**
- **Spring AOP 是如何解析我们配置的Aspect,生成 Advisors 链的?**
- **Spring AOP 是如何生成代理类的,如何将 advice 织入代理类?**
另外,整个源码解析的内容过多,为了读者的阅读体验和自己的时间安排。我将按照上面的总结的三点,分三篇向您解读。
> 本文的源码解析是以AOP注释方式使用来作为例子讲解的,和其他方式主要是在于触发入口不同,核心的流程还是差不多的。希望读者们能够触类旁通。
## 一、开启AOP自动代理的玄机
我们在[Spring AOP - 注解方式使用介绍(长文详解)](/archives/[%E7%BA%AF%E5%B9%B2%E8%B4%A7]%20%E5%A6%82%E4%BD%95%E7%94%A8Spring%20%E5%8E%9F%E7%94%9F%E6%B3%A8%E8%A7%A3%20%E5%BF%AB%E9%80%9F%E5%AE%9E%E7%8E%B0%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F+%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F)中介绍了`@EnableAspectJAutoProxy` 注解,是用来开启 Spring AOP注解的使用。这个的作用就是自动让 ioc 容器中的所有 advisor 来匹配方法,advisor 内部都是有 advice 的,让它们内部的 advice 来执行拦截处理(注:advisor 可以就看成 pointcut + advise的一个组合对象)。引用这个注解的英文翻译就是开启自动代理。
那么里面的玄机是什么呢?
我们进去先进到这个注解里面看看,
```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
```
`@Import(AspectJAutoProxyRegistrar.class)`使用`@Import` 注解将 `AspectJAutoProxyRegistrar`注入到 IoC 容器当中。
> 对这个注解不熟悉的可以去了解一下 [@Import Annotation in Spring Framework](https://javabeat.net/use-import-importing-javaconfig-files-spring-projects/)
我们看一看这个`AspectJAutoProxyRegistrar`,

注意,这个类实现了`ImportBeanDefinitionRegistrar`接口。
这个接口是一个**Spring 很强大的扩展接口**,它的作用是:
> Register additional bean definitions when processing @Configuration classes.
> Useful when operating at the bean definition level (as opposed to @Bean method/instance level) is desired or necessary.
就是说,**它需要和`@Configuration`配合使用**,在`@Configuration`之前已注册的Bean,可以由`ImportBeanDefinitionRegistrar`接口来处理,这个接口提供了如下一个方法:
```java
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)
```
这个方法可以拿到`@Import`的这个class的`Annotation Metadata`,以及此时的`BeanDefinitionRegistry`对象,通过`BeanDefinitionRegistry` 就可以拿到目前所有注册的BeanDefinition,可以自定义逻辑来动态注册一些你觉得必要的BeanDefinition。
> PS: 很多开源框架与Spring 集成的时候都扩展了这个接口,比如Apollo的ApolloConfigRegistrar 、mybatis的MapperScannerRegistrar等等
>
> 扩展阅读 https://www.logicbig.com/tutorials/spring-framework/spring-core/import-bean-registrar.html
在`AspectJAutoProxyRegistrar`中,实际上就是将`AspectJAnnotationAutoProxyCreator`的`BeanDefinition`注册到IoC 容器当中。
下面是`AopConfigUtils`中执行注册的逻辑代码片段。

------
先来一条分割线,理解完上面的流程之后,我们继续来思考。
为什么把`AspectJAnnotationAutoProxyCreator`注入到Spring IoC 容器中,自动代理就开启了呢?
让我们来寻找这个触发点。
## 二、自动代理的触发时机
首先,我们来看一下`AspectJAnnotationAutoProxyCreator`的继承结构。

有没有发现,`AspectJAnnotationAutoProxyCreator`居然是一个`BeanPostProcessor`!
**学习过 Spring IoC 之后的你,应该对这个类极其的敏感。**
```java
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
```
我们先回顾思考下代理模式的实现思路:**(接口) + 真实实现类 + 代理类**。
是不是要先有了真实的实现类,才能够生成代理类?!
在[Spring IoC - IoC 容器初始化 源码解析](/archives/Spring%20IoC%20%20-%20IoC%20%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB)中我们介绍了Spring Bean 创建的过程,在执行完 Step1 创建实例对象`createBeanInstance()`和 Step2 属性装配`populateBean()`之后,我们才算**得到一个真正的实现类**。
在Step3 `initializeBean()`中,IoC容器会处理Bean初始化之后的各种回调事件,然后返回一个“可能经过加工”的bean对象。
其中就包括了`BeanPostProcessor` 的 `postProcessBeforeInitialization` 回调 和 `postProcessAfterInitialization ` 回调。
而`AspectJAnnotationAutoProxyCreator`恰恰是一个`BeanPostProcessor`(原谅我又重复了一次),那就很容易联想到,Spring AOP 就是在这一步,**进行代理增强**!
## 三、初探代理类的生成流程
那么接下来,我们就来看看这里面的玄机。

可以看到实际回调的 `postProcessBeforeInitialization` 和 `postProcessAfterInitialization ` 这两个方式是在`AbstractAdvisorAutoProxyCreator` 中 override 的。
源码位置:`AbstractAdvisorAutoProxyCreator`

JavaDoc 很清楚的注明了`postProcessAfterInitialization `会执行创建代理类的操作,用配置的interceptors 来创建一个代理类,并且告诉我们去看`getAdvicesAndAdvisorsForBean`,看来这会是一个关键方法,这里我们先不急,继续往下看`wrapIfNecessary`方法。
源码位置:`AbstractAutoProxyCreator#wrapIfNecessary(..)`

这个方法里面有核心的就是两个点,我在上图中分别用`**** TODO-1 ****`和`**** TODO-2 ****`标识出来了。
`TODO-1`就是**获取当前的Spring Bean 适配的 advisors**。
`TODO-2`就是**创建代理类**。
------
我们接下去的章节就是详细讲解这两个`TODO`的内容。我们下次再会。

向您生动地讲解Spring AOP 源码(1)