在Spring AOP - 注解方式使用介绍(长文详解)中,做者介绍了Spring AOP 注解方式的使用方式。算是给我们的Spring AOP 源码分析开了个头,作了一点知识点的铺垫。html
在开始学习Spring AOP的源码以前,若是你尚未学习过Spring IoC的源码,最好先去学习下Spring IoC。java
Spring AOP 只做用于Spring Bean 的特性说明了Spring AOP和Spring IOC 的关系,AOP 依赖于 IOC 容器来管理,后面的源码分析也会涉及到Spring IoC 的源码内容。spring
下面,假设你已经学习过Spring IoC 的相关内容和Spring AOP的相关使用,让咱们开始吧。mybatis
本文耗费了做者大量心力,但愿能对你有所帮助。app
咱们前面一直说的Spring AOP源码解析,源码这么多,咱们真正关注的内容是什么?框架
Spring AOP的功能是什么?从使用上直白的说,就是根据咱们的配置来生成代理类,拦截指定的方法,将指定的advice织入。ide
咱们应该关注的内容总结下来就是:源码分析
另外,整个源码解析的内容过多,为了读者的阅读体验和本身的时间安排。我将按照上面的总结的三点,分三篇向您解读。post
本文的源码解析是以AOP注释方式使用来做为例子讲解的,和其余方式主要是在于触发入口不一样,核心的流程仍是差很少的。但愿读者们可以举一反三。学习
咱们在Spring AOP - 注解方式使用介绍(长文详解)中介绍了@EnableAspectJAutoProxy
注解,是用来开启 Spring AOP注解的使用。这个的做用就是自动让 ioc 容器中的全部 advisor 来匹配方法,advisor 内部都是有 advice 的,让它们内部的 advice 来执行拦截处理(注:advisor 能够就当作 pointcut + advise的一个组合对象)。引用这个注解的英文翻译就是开启自动代理。
那么里面的玄机是什么呢?
咱们进去先进到这个注解里面看看,
@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
咱们看一看这个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
接口来处理,这个接口提供了以下一个方法:
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 复制代码
这个方法能够拿到@Import
的这个class的Annotation Metadata
,以及此时的BeanDefinitionRegistry
对象,经过BeanDefinitionRegistry
就能够拿到目前全部注册的BeanDefinition,能够自定义逻辑来动态注册一些你以为必要的BeanDefinition。
PS: 不少开源框架与Spring 集成的时候都扩展了这个接口,好比Apollo的ApolloConfigRegistrar 、mybatis的MapperScannerRegistrar等等
在AspectJAutoProxyRegistrar
中,实际上就是将AspectJAnnotationAutoProxyCreator
的BeanDefinition
注册到IoC 容器当中。
下面是AopConfigUtils
中执行注册的逻辑代码片断。
先来一条分割线,理解完上面的流程以后,咱们继续来思考。
为何把AspectJAnnotationAutoProxyCreator
注入到Spring IoC 容器中,自动代理就开启了呢?
让咱们来寻找这个触发点。
首先,咱们来看一下AspectJAnnotationAutoProxyCreator
的继承结构。
有没有发现,AspectJAnnotationAutoProxyCreator
竟然是一个BeanPostProcessor
!
学习过 Spring IoC 以后的你,应该对这个类极其的敏感。
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
复制代码
咱们先回顾思考下代理模式的实现思路:(接口) + 真实实现类 + 代理类。
是否是要先有了真实的实现类,才可以生成代理类?!
在Spring IoC - 依赖注入 源码解析中咱们介绍了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
的内容。咱们下次再会。
若是本文有帮助到你,但愿能点个赞,这是对个人最大动力。