寻找入口
Spring 的 AOP 是通过接入 BeanPostProcessor 后置处理器开始的,它是 Spring IOC 容器经常使用到的一个特性,这个 Bean 后置处理器是一个监听器,可以监听容器触发的 Bean 声明周期事件。后置处
理器向容器注册以后,容器中管理的 Bean 就具备了接收 IOC 容器事件回调的能力。
BeanPostProcessor 的使用非常简单,只需要提供一个实现接口 BeanPostProcessor 的实现类,然后在 Bean 的配置文件中设置即可。
1、BeanPostProcessor 源码
这两个回调的入口都是和容器管理的 Bean 的生命周期事件紧密相关,可以为用户提供在 Spring IOC容器初始化 Bean 过程中自定义的处理操作。
2、AbstractAutowireCapableBeanFactory 类对容器生成的 Bean 添加后置处理器
BeanPostProcessor 后置处理器的调用发生在 Spring IOC 容器完成对 Bean 实例对象的创建和属性的依赖注入完成之后,在对Spring依赖注入的源码分析过程中我们知道,当应用程序第一次调用 getBean()方法(lazy-init 预实例化除外)向 Spring IOC 容器索取指定 Bean 时触发 Spring IOC 容器创建 Bean 实例 对 象 并 进 行 依 赖 注 入 的 过 程 , 其 中 真 正 实 现 创 建 Bean 对 象 并 进 行 依 赖 注 入 的 方 法 是AbstractAutowireCapableBeanFactory 类的 doCreateBean()方法,主要源码如下:
从上面的代码中我们知道,为 Bean 实例对象添加 BeanPostProcessor 后置处理器的入口的是initializeBean()方法。
3、initializeBean()方法为容器产生的 Bean 实例对象添加 BeanPostProcessor 后置处理器
同样在 AbstractAutowireCapableBeanFactory 类中,initializeBean()方法实现为容器创建的 Bean实例对象添加 BeanPostProcessor 后置处理器,源码如下:
BeanPostProcessor 是一个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类来实现,在 Spring 中,BeanPostProcessor 的实现子类非常的多,分别完成不同的操作,如:AOP 面向切面编程的注册通知适配器、Bean 对象的数据校验、Bean 继承属性、方法的合并等等,我们以最简单的AOP 切面织入来简单了解其主要的功能。下面我们来分析其中一个创建 AOP 代理对象的子类AbstractAutoProxyCreator 类。该类重写了 postProcessAfterInitialization()方法。
选择代理策略
进入 postProcessAfterInitialization()方法,我们发现调到了一个非常核心的方法 wrapIfNecessary(),其源码如下:
整个过程跟下来,我发现最终调用的是 proxyFactory.getProxy()方法。到这里我们大概能够猜到proxyFactory 有 JDK 和 CGLib 的,那么我们该如何选择呢?最终调用的是 DefaultAopProxyFactory的 createAopProxy()方法:
调用代理方法
分析调用逻辑之前先上类图,看看 Spring 中主要的 AOP 组件:
上面我们已经了解到 Spring 提供了两种方式来生成代理方式有 JDKProxy 和 CGLib。下面我们来研究一下 Spring 如何使用 JDK 来生成代理对象,具体的生成代码放在 JdkDynamicAopProxy 这个类中,直接上相关代码:
通过注释我们应该已经看得非常明白代理对象的生成过程,此处不再赘述。下面的问题是,代理对象生成了,那切面是如何织入的?我们知道 InvocationHandler 是 JDK 动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。而从 JdkDynamicAopProxy 的源码我们可以看到这个类其实也实现了 InvocationHandler,下面我们分析 Spring AOP 是如何织入切面的,直接上源码看 invoke()方法:
主要实现思路可以简述为:首先获取应用到此方法上的通知链(Interceptor Chain)。如果有通知,则应用通知,并执行 JoinPoint;如果没有通知,则直接反射执行 JoinPoint。而这里的关键是通知链是如何获取的以及它又是如何执行的呢?现在来逐一分析。首先,从上面的代码可以看到,通知链是通过Advised.getInterceptorsAndDynamicInterceptionAdvice()这个方法来获取的,我们来看下这个方法的实现逻辑:
通过上面的源码我们可以看到,实际获取通知的实现逻辑其实是由 AdvisorChainFactory 的getInterceptorsAndDynamicInterceptionAdvice()方法来完成的,且获取到的结果会被缓存。下面来分析 getInterceptorsAndDynamicInterceptionAdvice()方法的实现:
这个方法执行完成后,Advised 中配置能够应用到连接点(JoinPoint)或者目标类(Target Object)的 Advisor 全部被转化成了 MethodInterceptor,接下来我们再看下得到的拦截器链是怎么起作用的。
从 这 段 代 码 可 以 看 出 , 如 果 得 到 的 拦 截 器 链 为 空 , 则 直 接 反 射 调 用 目 标 方 法 , 否 则 创 建MethodInvocation,调用其 proceed()方法,触发拦截器链的执行,来看下具体代码:
至此,通知链就完美地形成了。我们再往下来看 invokeJoinpointUsingReflection()方法,其实就是反射调用:
Spring AOP 源码就分析到这儿,相信小伙伴们应该有了基本思路,下面时序图来一波