要研究这个原理,首先咱要从开启 AOP 的核心说起,那就是 **@EnableAspectJAutoProxy**
注解,
1. @EnableAspectJAutoProxy的作用
翻开 @EnableAspectJAutoProxy
注解的源码,可以发现它 @Import
了一个注册器:
复制 @Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
1.1 AspectJAutoProxyRegistrar与后置处理器
这个注册器还挺有来头,咱点进去看一眼它的文档注释,会发现它已经把核心的后置处理器给说出来了:
Registers an AnnotationAwareAspectJAutoProxyCreator against the current BeanDefinitionRegistry as appropriate based on a given @EnableAspectJAutoProxy annotation.
根据给定的 @EnableAspectJAutoProxy
注解,根据当前 BeanDefinitionRegistry
在适当的位置注册 AnnotationAwareAspectJAutoProxyCreator
。
由此可知,AOP 的核心后置处理器是 **AnnotationAwareAspectJAutoProxyCreator**
。
先把它放在一边,咱先了解一下 AspectJAutoProxyRegistrar
是在什么时机下注册 AnnotationAwareAspectJAutoProxyCreator
的。
1.2 AspectJAutoProxyRegistrar注册后置处理器的时机
由于 AspectJAutoProxyRegistrar
实现了 ImportBeanDefinitionRegistrar
接口,所以我们可以直接找到 registerBeanDefinitions
方法,去寻找注册的逻辑。
复制 public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 核心注册后置处理器的动作
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 解析@EnableAspectJAutoProxy的属性并配置
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
合着第一句就明示了它要注册后置处理器,也就是代理的创建器了。而这个方法也指明了它要注册的 bean 的类型就是 AnnotationAwareAspectJAutoProxyCreator
:
复制 public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
再往下,就是根据这个类型,构造 BeanDefinition
,并注册进 BeanDefinitionRegistry
的动作了,逻辑相对简单,小伙伴们扫一眼就可以了:
复制 private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 构造BeanDefinition,注册进BeanDefinitionRegistry
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
逻辑还是简单吧,经过 IOC 部分的洗礼,这些底层看起来是不是也就轻松许多了呢?
下面我们来着重研究这个核心的后置处理器,也就是代理对象的创建器 **AnnotationAwareAspectJAutoProxyCreator**
。
2. AnnotationAwareAspectJAutoProxyCreator
这么重要的 API ,javadoc 中一定有对它的描述吧,咱先来看一眼:
它是 AspectJAwareAdvisorAutoProxyCreator
的子类,用于处理当前 ApplicationContext 中的所有基于 AspectJ 注解的切面,以及 Spring 原生的 Advisor
。
如果 Spring AOP 基于代理的模型能够应用任何被 @AspectJ
注解标注的类,那么它们的增强方法将被自动识别。这涵盖了方法执行的切入点表达式。
如果使用 <aop:include>
元素,则只有名称与包含模式匹配的被 @AspectJ
标注的 bean 将被视为定义要用于 Spring 自动代理的方面。
Spring 中内置的 Advisor
的处理遵循 AbstractAdvisorAutoProxyCreator
中建立的规则。
拆解看来,javadoc 中解释的核心内容是,AnnotationAwareAspectJAutoProxyCreator
它兼顾 AspectJ 风格的切面声明,以及 SpringFramework 原生的 AOP 编程。
2.1 AnnotationAwareAspectJAutoProxyCreator的继承结构
借助 IDEA ,可以很清楚的看到 AnnotationAwareAspectJAutoProxyCreator
的继承结构,以及它其中的重要核心:
注意看最顶层的接口,它实现了几个重要的接口:
BeanPostProcessor
:用于在 postProcessAfterInitialization
方法中生成代理对象
InstantiationAwareBeanPostProcessor
:拦截 bean 的正常 doCreateBean
创建流程
SmartInstantiationAwareBeanPostProcessor
:提前预测 bean 的类型、暴露 bean 的引用( AOP 、循环依赖等,太过于复杂,此处不作解释)
AopInfrastructureBean
:实现了该接口的 bean 永远不会被代理(防止套娃)
除此之外,咱们一定要注意到它最开始的抽象实现类是 **AbstractAutoProxyCreator**
,它也是极度重要的!咱后面的不少源码分析中都会遇到它的。
2.2 AnnotationAwareAspectJAutoProxyCreator的初始化时机
既然在 AspectJAutoProxyRegistrar
中已经把 AnnotationAwareAspectJAutoProxyCreator
的 BeanDefinition
注册到 BeanDefinitionRegistry
中了,那么接下来的后置处理器初始化部分,它一定会被创建,而这个时机我们在前面 IOC 原理部分也讲过了,咱这里回顾一下:
复制 public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// ......
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册、初始化BeanPostProcessor
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
// ......
}
}
这里面那个超级长的方法,还有印象吧!源码咱就不贴了,主要能让小伙伴们回忆起来就好。
注意一个小细节,AnnotationAwareAspectJAutoProxyCreator
实现了 Ordered
接口,它会提前于普通 BeanPostProcessor
创建,那是不是就代表着普通的 BeanPostProcessor
也会被 AOP 代理呢?答案是肯定的,小伙伴们可以自行测试一下。
2.3 AnnotationAwareAspectJAutoProxyCreator的作用时机
那既然 ApplicationContext
的 refresh
方法中,第 6 步 registerBeanPostProcessors
方法把 AnnotationAwareAspectJAutoProxyCreator
初始化好了,接下来的 bean 就应该都会被它干预了。
2.3.1 getBean → doCreateBean
bean 的创建流程咱前面 IOC 原理部分已经学过了,从 getBean
开始,依次是 doGetBean
、createBean
、doCreateBean
,在 doCreateBean
方法中会真正的创建对象、属性赋值、依赖注入,以及初始化流程的执行。等 bean 本身的初始化流程全部执行完毕后,就该 BeanPostProcessor
的 postProcessAfterIntialization
方法了,这些咱都很熟悉。
不过,在这之前有一个小插曲,是 createBean
到 doCreateBean
这个动作中还有一个 InstantiationAwareBeanPostProcessor
的拦截初始化动作,咱需要来看一下。
2.3.2 AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation
源码不是特别长,我们可以简单的来看一下这里面发生的核心动作:
复制 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
// 决定是否要提前增强当前bean
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 被增强过的bean不会再次被增强
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 基础类型的bean不会被提前增强、被跳过的bean不会被提前增强
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 原型bean的额外处理:TargetSource
// 此处的设计与自定义TargetSource相关,单实例bean必定返回null
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
纵读下来,这里面的逻辑其实并不复杂,甚至还蛮容易理解的,这里面涉及到几个小概念咱在这里解释一下。
2.3.2.1 InfrastructureClass
这个基础类型 ,可能小伙伴们不大理解这玩意是个啥,咱可以点进去看看:
复制 protected boolean isInfrastructureClass(Class<?> beanClass) {
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
// logger ......
return retVal;
}
得了,合着它说的这些基础类型,是切面、切入点、增强器等等的对象 !那一切就解释的过去了,一个切入点的对象包装怎么会被 AOP 代理呢?它是作为 AOP 底层非常重要的组成成员,它不应该参与到具体的被增强对象中。
2.3.2.2 被跳过的bean?
这个被跳过的 bean ,似乎在之前我们学习 AOP 的过程中一直没有接触过,它是什么意思呢?咱可以先进到源码中看看:
复制 // AspectJAwareAdvisorAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 加载增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 逐个匹配,如果发现当前bean的名称与增强器的名称一致,则认为
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
// AbstractAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 检查beanName代表的是不是原始对象(以.ORIGINAL结尾)
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
简单的用注释一标,小伙伴们也不难理解这段逻辑吧,它要看看当前对象的名称是不是有跟增强器的名称撞车的 ,或者说它是不是一个还没有经过任何代理的原始对象 。对于一般情况而言,我们构造的 bean 根本就不可能带有 .ORIGINAL
的后缀,所以这个地方相当于判断当前创建的 bean 是否名称与增强器撞车。
这里咱简单说下增强器的概念。一个 Advisor
可以视为一个切入点 + 一个通知方法的结合体 ,对于 Aspect 切面类中定义的通知方法,方法体 + 方法上的通知注解 就可以看做一个 Advisor
增强器。更多相关的解释,咱放到下一章再研究。
至于上面的 findCandidateAdvisors
方法,里面的逻辑有点复杂,咱也放到下一章再研究。
不过在此 Debug 的时候,可以发现 findCandidateAdvisors
方法执行完成后,获取到了 5 个增强器,也都是在 Logger
类中定义的那 5 个通知方法:
(最后一个名太长了,实际上是 afterThrowing 的通知,引用的通用切入点表达式罢了。。。)
2.3.2.3 TargetSource?
这个概念咱之前在 IOC 部分没有见到过,当然它也不是 IOC 的东西。。。这个概念咱也是放到下一章再解释吧,这里咱可以先简单说一下,AOP 的代理其实不是代理的目标对象本身,而是目标对象包装后的 **TargetSource**
对象 。至于为什么它会这么做,咱下一章也会展开解释的。
2.3.3 AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization
前面的拦截判断结束后,AnnotationAwareAspectJAutoProxyCreator
再发挥作用就要等到最后一步的 postProcessAfterInitialization
方法了,这里面就是真正的生成代理对象。方法的实现很简单,咱跳转进来看一下:
复制 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 核心:构造代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
小小的前戏后,最关键的动作是中间的 wrapIfNecessary
方法。
这个动作从方法名上就可以很容易的理解了,如果有必要的话,给这个对象包装生成代理对象。下面进入到源码的部分:
复制 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 如果上面的判断都没有成立,则决定是否需要进行代理对象的创建
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象的动作
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
所以由此可见,创建代理对象的核心动作其实就三个步骤: