前言:
Spring AOP 是一个非常常见的概念,使用了 Spring 的项目大多数也都用了 Spring AOP 的功能,比如我们常见的日志统计、事务管理等,AOP 的全称是 “Aspect Oriented Programming”,也是我们常说的⾯向切⾯编程,那你真的了解 Spring AOP 的原理吗?
AOP 基础知识
AOP 概念
- 连接点(Join point):能够被拦截的地⽅、地点,Spring AOP 是基于动态代理的,所以是⽅法拦截的,每个成员⽅法都可以称之为连接点。
- 切点(Poincut):匹配连接点的断言,在AOP中通知和一个切入点表达式关联,切点分为execution方式和annotation方式,前者可以用路径表达式指定哪些类织入切面,后者可以指定被哪些注解修饰的代码织入切面。
- 通知(Advice):在切面的某个特定的连接点上执行的动作,通知分为:前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能)。
- 织⼊(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象,分为:编译时织入、类加载时织入、执行时织入
- 引⼊/引介(Introduction):允许我们向现有的类添加新⽅法或属性,是⼀种特殊的增强。
- 切面(Aspect):切⾯由切点和增强、通知组成,它既包括了横切逻辑的定义、也包括了连接点的定义。
通知(Advice)分类
- 前置通知(Before Advice):在⽬标⽅法被调⽤前的通知功能。
- 后置通知(After Advice):在⽬标⽅法被调⽤之后的通知功能。
- 返回通知(After-returning):在⽬标⽅法成功执⾏之后的通知功能。
- 异常通知(After-throwing):在⽬标⽅法抛出异常之后的通知功能。
- 环绕通知(Around):把整个⽬标⽅法包裹起来,在被调⽤前和调⽤之后的通知功能。
理解 Spring AOP 之前需要对 Spring Bean 的创建过程及 Bean 生命周期有一定理解,相关知识传送门如下:
深入理解 Spring IOC 底层实现机制(refresh 方法源码分析)
Spring 源码之 BeanDefinition 加载分析
Spring AOP 实现原理概述:
- 将所有切面保存在切面缓存中。
- Bean 对象属性填充后,从切面缓存中取出所有方法和 Bean 对象的方法进行匹配,找到 Bean 对象的所有切面方法。
- 创建 AOP 代理,有 JDK 动态代理和 Cglib 动态代理两种方式,Spring动态代理默认使用 CGlib。
- 通过 责任链 + 递归 模式去执行切面逻辑。
Spring AOP 代码调用链路简图
简单梳理了 Spring AOP 从容器加载 Bean 到 Bean 的前置处理、创建代理对象、代理对象的调用的整个过程的代码调用链路图,Spring AOP 底层涉及到的代码非常多,简图只梳理了相对核心的步骤,Spring AOP 源码分析也会根据这个核心进行分析。
Spring AOP 源码分析
Spring 容器加载 Bean 相关的源码前面篇章有做过分析,就不在本篇进行分析了,感兴趣的伙伴可以通过传送门去看看,本篇核心点是分析 Spring AOP 相关源码。
Bean 前置处理
Bean 前置处理之 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation 源码分析
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation 方法通过 RootBeanDefinition 相关属性,判断 Bean 是否有 BeanPostProcessor,是否是有应用程序自动生成(AOP),满足条件就继续调用 BeanPostProcessor 的前置处理。
//AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
//如果Bean配置了初始化前和初始化后的处理器 则试图返回一个需要创建Bean的代理对象,在这个方法中会判断对象是否存在
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
//第一次进来 mbd.beforeInstantiationResolved 为 null Boolean 默认值为 null
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
//mbd.isSynthetic():bean 是否是合成的 即未定义)(不是有代码生成) 由应用程序自动生成 例如 AOP 代理
//hasInstantiationAwareBeanPostProcessors:是否有 bean 后置处理器
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
//获取指定 beanName 的class
Class<?> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
//在实例化前执行应用 bean 后置处理器 (后置处理器的前置处理 缓存切面)
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//bean 不为空 进行 bean 后置处理器的后置处理(AOP 生成代理对象)
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
//重新赋值 beforeInstantiationResolved
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
Bean 前置处理之 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation 源码分析
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation 方法是获取 Bean 所有的 BeanPostProcessor,然后调用 BeanPostProcessor 的 postProcessBeforeInstantiation 方法,执行 Bean 实例化的前置增强操作(缓存切面–本篇分析的重点)。
//AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
//调用指定 beanName 的所有 BeanPostProcessor 执行实例化前的后置处理方法
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
//从缓存中获取 bean 的后置处理器
Iterator var3 = this.getBeanPostProcessorCache().instantiationAware.iterator();
Object result;
do {
if (!var3.hasNext()) {
return null;
}
//将 beanPostProcessor 转换为 InstantiationAwareBeanPostProcessor InstantiationAwareBeanPostProcessor 继承了 BeanPostProcessor 接口
InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var3.next();
//实例化前的后置处理
result = bp.postProcessBeforeInstantiation(beanClass, beanName);
} while(result == null);
return result;
}
Bean 前置处理之 AbstractAutoProxyCreator#postProcessBeforeInstantiation 源码分析
AbstractAutoProxyCreator#postProcessBeforeInstantiation 先从缓存中获取指定 beanName 的 Bean,判断当前 Bean 是否已经执行过实例化前增强,以及一些相关判断,当前方法中的重点是 this.shouldSkip(beanClass, beanName) 方法。
//AbstractAutoProxyCreator#postProcessBeforeInstantiation
//bean 实例化前的后置处理
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//尝试从缓存中获取 指定beanName 的 bean
Object cacheKey = this.getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//被增强的 bean 中是否有当前 bean 有的话 就不需要在增强了
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//this.isInfrastructureClass(beanClass):InfrastructureClass直译为“基础类型” 它指代的是IOC容器中注册的基础类 包括切面类、切入点、增强器等 bean 对象
//this.shouldSkip(beanClass, beanName):是否需要跳过(被跳过的bean对象不会被提前增强) 本篇重点分析的方法
if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
//当前bean加入缓存中 表示不需要增强
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//获取当前对象的自定义 targetSource 在创建代理对象的时候 会把当前对象包装成一个 targetSource 交给代理类 用于找到对象自身
TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
//targetSource 不为空 beanName 不为空 beanName加入 自定义 targetSourcedBeans 中
this.targetSourcedBeans.add(beanName);
}
//获取指定 beanName 的通知过顾问(Advisors 是 spring 中 aop定义切面 通常由一个切点和一个通知组成(是通知的封装及延伸) aspect 是 AOP 规范切面 允许由多个切点和多个通知组成)
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
//创建代理
Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource);
//加入缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
return null;
}
}
Bean 前置处理之 AspectJAwareAdvisorAutoProxyCreator#shouldSkip 源码分析
AspectJAwareAdvisorAutoProxyCreator#shouldSkip 方法是重点方法,来到这个方法里面,我们已经可以看到一些更 AOP 相关的概念了,比如增强器,也叫顾问的 Advisor,shouldSkip 方法会获取准备增强的 Bean 对象的所有增强器,遍历逐个检查当前准备增强的 bean 对象是否与增强器的名称一致,如果一致则跳过,不能被增强,也就是说 shouldSkip 方法要检查当前准备增强的 bean 对象是否是一个还没有经过任何代理的原始对象,检查的规则是根据 bean 对象的名称是否带有 .ORIGINAL 的后缀,如果是一个原始对象,则跳过不进行增强,我们会对 this.findCandidateAdvisors() 进行重点分析。
//AspectJAwareAdvisorAutoProxyCreator#shouldSkip
//是否跳过
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
//查找 增强器 顾问 Advisor 重点分析的方法
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
//迭代遍历
Iterator var4 = candidateAdvisors.iterator();
Advisor advisor;
do {
if (!var4.hasNext()) {
//检查 beanName 代表的是不是原始对象
return super.shouldSkip(beanClass, beanName);
}
advisor = (Advisor)var4.next();
//advisor instanceof AspectJPointcutAdvisor:advisor 是否是 AspectJPointcutAdvisor 子类
//(AspectJPointcutAdvisor)advisor).getAspectName().equals(beanName):检查当前准备增强的 beanName 是否与增强器的名称一致
//只有都满足的时候才增强
} while(!(advisor instanceof AspectJPointcutAdvisor) || !((AspectJPointcutAdvisor)advisor).getAspectName().equals(beanName));
return true;
}
//AbstractAutoProxyCreator#shouldSkip
//AbstractAutoProxyCreator 是 AspectJAwareAdvisorAutoProxyCreator 的父类
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 检查beanName代表的是不是原始对象(以.ORIGINAL结尾)
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
Bean 前置处理之 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors 源码分析
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors 方法的作用就是获取增强器 Advisor,该方法会获取 Spring 的原生增强器和 AspectJ 切面增强器,我们重点分析 AspectJ 切面增强器,也就是 this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 方法。
//AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
//查询增强器
protected List<Advisor> findCandidateAdvisors() {
// 根据父类的规则添加所有找到的 Spring 原生的增强器
List<Advisor> advisors = super.findCandidateAdvisors();
//解析BeanFactory中所有的AspectJ切面,并构建增强器
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
Bean 前置处理之 BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors 源码分析
BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors 方法会遍历所有的类,判断是否是切面,是切面才会进入切面的逻辑,进行一些列的相关判断,最终把切面缓存到增强器 advisorsCache 中缓存 ,至此 AOP Bean 前置处理分析完毕。
//BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
//构建 AspectJ 增强器
public List<Advisor> buildAspectJAdvisors() {
//获取切面 bean 对象名称
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
//同步保证线程安全问题
synchronized(this) {
//再次获取 类似 double check
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
//存储 增强器 Advisor
List<Advisor> advisors = new ArrayList();
//存储 aspectNames
List<String> aspectNames = new ArrayList();
//获取所有bean 对象名称
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
String[] var18 = beanNames;
int var19 = beanNames.length;
//遍历 bean 对象
for(int var7 = 0; var7 < var19; ++var7) {
String beanName = var18[var7];
//判断当前bean是否为子类定制的需要过滤的bean
if (this.isEligibleBean(beanName)) {
//通过制定 beanName 获取对应的 class 对象
Class<?> beanType = this.beanFactory.getType(beanName);
//beanType 不为空 且 this.advisorFactory.isAspect(beanType) 当前 bean 使用了 Aspect 注解
if (beanType != null && this.advisorFactory.isAspect(beanType)) {
//保存到切面集合中
aspectNames.add(beanName);
//使用了@Aspect注解标注的 bean 将其封装为一个 AspectMetadata
AspectMetadata amd = new AspectMetadata(beanType, beanName);
//判断@Aspect注解中标注的是否为 singleton 类型 默认的切面类都是singleton类型
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
//把指定 beanName 封装成一个 MetadataAwareAspectInstanceFactory
MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//通过封装的 factory 获取欧 bean 的 dvice 如@Before,@After等 并且将这些 Advice都解析并且封装为一个个的Advisor
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
//如果切面类是 singleton 类型 则将解析得到的 Advisor 进行缓存
this.advisorsCache.put(beanName, classAdvisors);
} else {
//不是 singleton 类型 则将封装的当前的factory进行缓存 以便再次获取时可以通过factory直接获取
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
} else {
//不是单例的
//这里再次判断 如果这里判断是单例的则抛出异常
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton");
}
//将当前切面 bean 封装为一个多例类型的 Factory
MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
//进行缓存
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
} else {
// 通过所有的aspectNames在缓存中获取切面对应的Advisor,这里如果是单例的,则直接从advisorsCache
// 获取,如果是多例类型的,则通过MetadataAwareAspectInstanceFactory立即生成一个
List<Advisor> advisors = new ArrayList();
//迭代遍历 aspectNames
Iterator var3 = aspectNames.iterator();
while(var3.hasNext()) {
//获取切面名称
String aspectName = (String)var3.next();
//从单例缓存中获取切面对应的增强器
List<Advisor> cachedAdvisors = (List)this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
} else {
//单例中获取不到 封装为一个 MetadataAwareAspectInstanceFactory 加入多例缓存中
MetadataAwareAspectInstanceFactory factory = (MetadataAwareAspectInstanceFactory)this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
}
经过以上的步骤,通知方法收集完毕,Advisor 增强器也创建完成,创建好的增强器将会在 Bean 对应的初始化阶段中等待织入,也就是创建代理。
创建代理对象
我们知道创建代理对象是 Bean 完成实例化后在初始化的时候创建的代理对象,也就是说我们要回到 AbstractAutowireCapableBeanFactory#doCreateBean 的 AbstractAutowireCapableBeanFactory#initializeBean 方法中去寻找相关逻辑,同样关于 Bean 的加载到 doCreateBean 方法的源码我们不在分析,有需要的小伙伴可以通过传送门去研究,我们直接从 initializeBean 方法开始着手分析代理对象的创建过程。
创建代理对象之 AbstractAutowireCapableBeanFactory#initializeBean 源码分析
AbstractAutowireCapableBeanFactory#initializeBean 方法主要是对实例化的 Bean 进行初始化操作,包括安全验证、对象属性包装、BeanPostProcessors 初始化前处理、Bean 对象的初始化 init-method、BeanPostProcessors 初始化后处理,这里我们主要关注 BeanPostProcessors 初始化后处理,也就是 this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName) 这行代码。
//AbstractAutowireCapableBeanFactory#initializeBean
//初始容器创建的Bean实例对象,为其添加 BeanPostProcessor 后置处理
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
//JDK的安全机制验证权限
if (System.getSecurityManager() != null) {
//匿名内部类
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//在初始化前 将 BeanPostProcessors 应用到现有的bean 实例 调用他们的 postProcessBeforeInitialization 方法
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//调用Bean实例对象初始化的方法 这个初始化方法是在Spring Bean定义配置
//文件中通过init-method属性指定的
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
//初始化后 将BeanPostProcessors 应用到现有的bean 实例 调用他们的 postProcessAfterInitialization 方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
创建代理对象之 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization 源码分析
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization 方法逻辑比较简单,就是遍历一系列的 BeanPostProcessor 调用其 postProcessAfterInitialization 方法。
//AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
//遍历 BeanPostProcessors 调用 processor.postProcessAfterInitialization 方法
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
//调用 processor.postProcessAfterInitialization 方法
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
创建代理对象之 AbstractAutoProxyCreator#postProcessAfterInitialization 源码分析
AbstractAutoProxyCreator#postProcessAfterInitialization 方法逻辑也很简单,从缓存中获取 Bean,判断在 Bean 的早期引用中是否有当前 Bean,如果没有就尝试创建 Bean 的代理对象,我们重点关注 this.wrapIfNecessary(bean, beanName, cacheKey) 这行代码。
//AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//根据 class 和 beanName 从缓存中获取
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
//在bean 的早期引用缓存中是否有 当前baan
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//没有当前 bean 尝试创建代理对象
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
创建代理对象之 AbstractAutoProxyCreator#wrapIfNecessary 源码分析
AbstractAutoProxyCreator#wrapIfNecessary 方法是 AOP 流程的核心方法,是真正创建代理对象的核心方法,该方法先是判断了当前 Bean 是否需要增强,然后获取当前 Bean 的所有增强器,根据得到的增强器完成代理对象的创建,wrapIfNecessary 方法中我们重点关注 this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null) 和 this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)) 方法。
//AbstractAutoProxyCreator#wrapIfNecessary
//创建代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
//beanName 为空 或者 targetSourcedBeans 中有当前 bean 直接返回
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
//Boolean.FALSE.equals(this.advisedBeans.get(cacheKey)):通过缓存判断该对象是否已经检测过 并且检测结果是不需要代理 直接返回
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//this.isInfrastructureClass(bean.getClass()):是否是切面类
//this.shouldSkip(bean.getClass(), beanName):是否需要跳过
if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
//获得当前 Bean 所有的增强器 找到候选的增强器 并且获得能被使用的增强器。返回拍好序的增强器链
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
//增强器不为空 缓存当前 bean 增强器不为空
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建当前bean的代理对象 spring自动决定创建哪种 默认是用 Cglib 代理
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
//缓存当前增强器为空
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
//缓存当前增强器为空
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
创建代理对象之 AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean源码分析
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean 方法没有什么逻辑,就是进行了方法包装,我们继续看 this.findEligibleAdvisors(beanClass, beanName) 这行代码。
//AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//寻找合格的增强器
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
创建代理对象之 AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 源码分析
AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 方法就是从缓存中获取所有增强器,然后通过匹配找到当前 Bean 的增强器,如果当前 Bean 的增强器有顺序,再排序后返回,我们重点分析 this.findCandidateAdvisors() 和 this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName) 这两行代码。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//寻找候选增强器 其实就是从缓存中查询所有增强器(bean 前置处理的时候 把增强器加入了缓存)
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
//从所有增强器中找到 当前 bean 的增强器
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对有@Order 注解的增强器排序
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
创建代理对象之 AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 源码分析
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors 方法就是从缓存中获取所有增强器,我们看到了熟悉的 super.findCandidateAdvisors() 和 this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 方法,这在 Bean 的前置处理中我们已经分析过,就是利用 BeanPostProcessor 把 Bean 的 Aspect 切面进行缓存,现在要创建代理对象了,就在这里取出使用。
//AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
// 根据父类的规则添加所有找到的 Spring 原生的增强器
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
///解析BeanFactory中所有的AspectJ切面 并构建增强器
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
创建代理对象之 AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply(List candidateAdvisors, Class<?> beanClass, String beanName) 源码分析
AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply 方法没有什么实际性的逻辑操作,就是调用了 AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass) 这个方法,我们继续分析。
//AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
//从所有增强器中找到指定 beanName 的增强器
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
//设置当前代理 bean 的名称 也就是记录现在正在处理的AOP BeanDefinition
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
List var4;
try {
//从所有增强器中查找当前 bean 的增强器
var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
//清空记录
ProxyCreationContext.setCurrentProxiedBeanName((String)null);
}
return var4;
}
引介增强和普通增强:
引介增强:是一种特殊的增强,其他增强是方法级别的增强,即只能增强在方法前或者方法后增强,而引介增强则不是作用于方法上的增强,而是作用于类上的增强,它可以为目标类动态实现某个接口,或者动态添加某些方法,引介增强的实现类要去实现引介增强接口 IntroductionInterceptor。
普通增强:方法级别的增强,常用的一些增强器的注解如 @Before、@After、@Around、@AfterThrowing、@AfterReturing,普通增强的实现类需要实现 PointcutAdvisor 接口。
创建代理对象之 AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply(List candidateAdvisors, Class<?> clazz) 源码分析
findAdvisorsThatCanApply 方法主要是对所有增强器进行引介增强和普通增强区分处理,判断哪些是当前需要的增强器,主要是看 AopUtils#canApply 方法。
//AopUtils#findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
//如果所有增强器为空 直接返回
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
} else {
//存放当前 bean 的增强器
List<Advisor> eligibleAdvisors = new ArrayList();
//迭代遍历所有增强器
Iterator var3 = candidateAdvisors.iterator();
while(var3.hasNext()) {
Advisor candidate = (Advisor)var3.next();
//candidate instanceof IntroductionAdvisor:当前增强器是否实现了 IntroductionAdvisor 引介增强 接口
//canApply:对引介增强的处理
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
//满足条件 加入到当前增强器 list 中
eligibleAdvisors.add(candidate);
}
}
//判断当前 bean 的增强器list 是否为空
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
//再次迭代遍历 所有增强器
Iterator var7 = candidateAdvisors.iterator();
while(var7.hasNext()) {
Advisor candidate = (Advisor)var7.next();
//!(candidate instanceof IntroductionAdvisor):没有实现 IntroductionAdvisor 引介增强接口 也就是普通增强
//canApply(candidate, clazz, hasIntroductions): 其实就是对 普通增强 的处理
if (!(candidate instanceof IntroductionAdvisor) && canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
}
创建代理对象之 AopUtils#canApply 源码分析
AopUtils#canApply 是真正判断一个增强器是否是当前需要的增强器的方法,通过放射获取类的所有方法,再和切点方法匹配器完成匹配来判断是否是需要的增强器,至此寻找增强器的过程分析完毕,现在要开始真正的创建代理对象了。
//AopUtils#canApply
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
//AopUtils#canApply
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
//引介增强 IntroductionAdvisor 和 普通增强 PointcutAdvisor 的区别在于 PointcutAdvisor 的切入点更细 我们这里的Advisor都是PointcutAdvisor 类型
if (advisor instanceof IntroductionAdvisor) {
//引介增强 判断该增强是否可以应用在targetClass上 如果可以则返回true 否则返回false
return ((IntroductionAdvisor)advisor).getClassFilter().matches(targetClass);
} else if (advisor instanceof PointcutAdvisor) {
//增强器转换为 切点增强器
PointcutAdvisor pca = (PointcutAdvisor)advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
} else {
return true;
}
}
//AopUtils#canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
//如果 Pointcut不能应用于 targetClass 类上 则直接返回false
return false;
} else {
//获取切点的方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
//完成匹配
return true;
} else {
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
//果是引介增强类型的方法匹配器则转化为引介增强的
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher)methodMatcher;
}
//将需要代理的类相关的接口加入集合中
Set<Class<?>> classes = new LinkedHashSet();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
//将这个类所有有关的接口都存储在classes中
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
Iterator var6 = classes.iterator();
while(var6.hasNext()) {
Class<?> clazz = (Class)var6.next();
//反射获取类的所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
Method[] var9 = methods;
int var10 = methods.length;
//遍历类的所有方法
for(int var11 = 0; var11 < var10; ++var11) {
Method method = var9[var11];
//判断方法是否匹配
if (introductionAwareMethodMatcher != null) {
if (introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) {
//匹配返回 true
return true;
}
} else if (methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
}
}
再次回到 AbstractAutoProxyCreator#wrapIfNecessary 方法,分析代理对象的创建过程,我们继续分析 this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)) 这行代码。
创建代理对象之 AbstractAutoProxyCreator#createProxy 源码分析
AbstractAutoProxyCreator#createProxy 方法主要是创建了代理工厂,以及做了一些代理对象创建的准备工作,我们重点关注 proxyFactory.getProxy(this.getProxyClassLoader())这行代码。
//AbstractAutoProxyCreator#createProxy
//创建代理对象
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
}
//创建 代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
//将当前对象的信息复制到代理工厂
proxyFactory.copyFrom(this);
//判断当前bean 是使用 TargetClass 代理还是接口代理
if (!proxyFactory.isProxyTargetClass()) {
//检查 proxyTargeClass 设置
if (this.shouldProxyTargetClass(beanClass, beanName)) {
//设置使用 TargetClass 而不是接口代理
//Cglib 代理:true
//jdk 代理:false
proxyFactory.setProxyTargetClass(true);
} else {
//代理接口
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//获取所有增强器
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
//增强器添加到代理工厂中
proxyFactory.addAdvisors(advisors);
//设置被代理的类
proxyFactory.setTargetSource(targetSource);
//自定义代理方法 默认空实现
this.customizeProxyFactory(proxyFactory);
//默认false 表示代理被配置后 就不允许修改它的配置了
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//获取代理对象
return proxyFactory.getProxy(this.getProxyClassLoader());
}
创建代理对象之 ProxyFactory#getProxy 源码分析
ProxyFactory#getProxy 方法只有一行代码,创建 AopProxy,根据 AopProxy 获创建理类,这里我们只分析创建 AopProxy 的过程。
//ProxyFactory#getProxy
//获取代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
//创建 AopProxy 获取代理类
return this.createAopProxy().getProxy(classLoader);
}
创建代理对象之 ProxyCreatorSupport#createAopProxy 源码分析
ProxyCreatorSupport#createAopProxy 方法主要就是调用了 DefaultAopProxyFactory#createAopProxy 的方法来判断返回 ObjenesisCglibAopProxy 还是返回 JdkDynamicAopProxy 。
//ProxyCreatorSupport#createAopProxy
//创建 AopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
//DefaultAopProxyFactory#createAopProxy
//创建 AopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//NativeDetector.inNativeImage():本机检查
//config.isOptimize():用来控制通过 CGLIB 创建的代理是否使用激进的优化策略 除非完全了解 AOP 代理如何处理优化 否则不推荐用户使用这个设置 目前这个属性仅用于CGLIB代理 对于JDK动态代理(默认代理)无效
//hasNoUserSuppliedProxyInterfaces(config) :是否存在代理接口
//isProxyTargetClass():这个属性为true时 目标类本身被代理而不是目标类的接口 如果这个属性值被设为true CGLIB代理将被创建
if (NativeDetector.inNativeImage() || !config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
//创建 JDK 动态dialing
return new JdkDynamicAopProxy(config);
} else {
//获取 targetClass
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
//targetClass.isInterface() 是否是接口
//targetClass 是代理类
//不是接口且不是代理类 才返回 Cglib 代理 否则返回 JDK 代理
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
至此,代理对象的创建过程已经分析完毕,我们接着分析代理对象的调用。
代理对象调用(切面执行)-- DynamicAdvisedInterceptor#intercept 源码分析
CglibAopProxy 代理切面执行的入口方法是 DynamicAdvisedInterceptor#intercept,核心是创建一个 CglibMethodInvocation 对象,调用父类的 ReflectiveMethodInvocation 的 proceed 方法,每次调用时将索引的值递增,从拦截器链中获取下一个需要执行的拦截器,判断是否是InterceptorAndDynamicMethodMatcher 动态方法匹配拦截器类型还是普通拦截器类型,然后分别做不同的处理,一直递归调用,直到所有拦截器执行完毕。
//DynamicAdvisedInterceptor#intercept
//Cglib AOP 回调
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//老的代理对象
Object oldProxy = null;
//是否设置代理上下文
boolean setProxyContext = false;
Object target = null;
//获取 targetSource targetSourc e实际上就是对目标对象实例进行封装的对象
TargetSource targetSource = this.advised.getTargetSource();
Object var16;
try {
//如果 exposeProxy 属性为true(默认false) 表示需要暴露代理对象
if (this.advised.exposeProxy) {
//将 proxy 也就是代理对象 通过 AopContext.setCurrentProxy 设置到 AopContext 内部的 ThreadLocal 线程本地变量中 currentProxy 是一个 ThreadLocal 线程本地变量
// 这样我们就能在原始方法中通过 AopContext.currentProxy()方法直接获取当前的代理对象 这个设置主要用来解决同一个目标类的方法互相调用时代理不生效的问题
oldProxy = AopContext.setCurrentProxy(proxy);
//代理上下文设置为 true
setProxyContext = true;
}
//获取原始目标对象 也就是被代理的对象
target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
//简单来说就是获取匹配当前方法的拦截器链
//也就是将代理对象创建过程中 设置到 proxyFactory 中的 advisors 集合中的 Advisor 进行筛选
//因为 advisors 中的拦截器一定是当前方法所属的类以及类中的某些方法 但并不一定匹配当前的方法 比如expression不匹配
//因此这里需要获取匹配当前方法的 Advisor 中的拦截器链列表 用于拦截当前方法并进行增强
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//如果当前方法的拦截器链为空
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
//如有必要 调整参数(直译...) 根据给定方法中的需要参数类型调整参数数组类型
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//反射通过目标类调用当前方法
retVal = methodProxy.invoke(target, argsToUse);
} else {
//当前方法的拦截器链不为空 创建一个 CglibMethodInvocation 对象 CglibMethodInvocation 继承了 ReflectiveMethodInvocation 随后调用 ReflectiveMethodInvocation 的 proceed 方法
//proceed 进行方法的代理和增强 proceed 方法是核心方法
retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
}
//将返回值替换为代理对象本身
retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
var16 = retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var16;
}
//CglibMethodInvocation#proceed
public Object proceed() throws Throwable {
try {
//调用父类 ReflectiveMethodInvocation 的 proceed方法
return super.proceed();
} catch (RuntimeException var2) {
throw var2;
} catch (Exception var3) {
if (ReflectionUtils.declaresException(this.getMethod(), var3.getClass())) {
throw var3;
} else {
throw new UndeclaredThrowableException(var3);
}
}
}
//ReflectiveMethodInvocation#proceed
@Nullable
public Object proceed() throws Throwable {
// 如果所有拦截器都执行完毕(currentInterceptorIndex = -1 是从-1开始 所以跟size - 1比较) 则直接使用反射调用连接点(也就是我们原本的方法)
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
//每次调用时 将索引的值递增 并通过索引拿到要执行的拦截器
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//判断拦截器是否为 InterceptorAndDynamicMethodMatcher 类型
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
//进行动态匹配。在此评估动态方法匹配器:静态部件已经过评估并且发现匹配
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
//动态匹配 成功 执行 invoke 方法 失败 跳过此拦截器并调用链中的下一个
return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
} else {
//只是一个普通的拦截器 则触发拦截器链责任链的调用 并且参数为 ReflectiveMethodInvocation 本身
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
//ExposeInvocationInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = (MethodInvocation)invocation.get();
//将MethodInvocation对象存入ThreadLocal中
invocation.set(mi);
Object var3;
try {
//执行链中下一个拦截器的逻辑
var3 = mi.proceed();
} finally {
//重置原来的MethodInvocatio
invocation.set(oldInvocation);
}
return var3;
}
关于AOP 切面的执行流程可以参考一下博文:
欢迎提出建议及对错误的地方指出纠正。