Spring源码系列文章
Spring源码解析(二):bean容器的创建、默认后置处理器、扫描包路径bean
Spring源码解析(六):bean工厂后置处理器ConfigurationClassPostProcessor
Spring源码解析(七):bean后置处理器AutowiredAnnotationBeanPostProcessor
Spring源码解析(八):bean后置处理器CommonAnnotationBeanPostProcessor
Spring源码解析(九):AOP源码之@Aspect所有相关注解解析
Spring源码解析(十):spring整合mybatis源码
Spring源码解析(十二):TransactionInterceptor事务拦截器
目录
一、AOP简介
- AOP是一种思想,它的实现主要有
Spring AOP
和AspectJ
- spring AOP底层实现是jdk和cglib动态代理
- 运行期织入
- 借助了AspectJ的语法,即使用了@Aspect @Before @Pointcut等注解来实现
- AspectJ主要原理是用asm做字节码替换来达到AOP的目的,需要使用专门的编译器
ajc
- 编译期、编译期后、类加载期都可以织入
AnnotationAwareAspectJAutoProxyCreator主要类图
- AOP的操作流程都在
AnnotationAwareAspectJAutoProxyCreator
类中 - 添加
@EnableAspectJAutoProxy
注解由@Import注解导入而来
- 实现BeanPostProcessor、InstantiationAwareBeanPostProcessor等bean后置处理器
- 查看AbstractAutoProxyCreator结构
- 获取提前暴露bean方法(创建并返回代理对象)
实例化前
寻找增强器并缓存初始化后
创建代理对象
二、AnnotationAwareAspectJAutoProxyCreator的注册
配置类
@Configuration
@ComponentScan(value = "com.xc")
/**
* Spring AOP 默认使用 JDK 动态代理
*
* proxyTargetClass = true 时则代理目标对象时强制使用 CGLIB 代理
* @see DefaultAopProxyFactory#createAopProxy(org.springframework.aop.framework.AdvisedSupport)
*
* exposeProxy = true 暴露代理对象,这样就可以使用 AopContext.currentProxy() 方法获取当前代理的对象
* @see AopContext#currentProxy
* @see JdkDynamicAopProxy#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*
* 可以解决在方法里面调方法,或者用 this 关键字调方法,而无法被代理的情况
**/
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class AopConfig {
}
@EnableAspectJAutoProxy注解
- 这个注解上面导入了一个
AspectJAutoProxyRegistrar
类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
- 它实现了ImportBeanDefinitionRegistrar,通过registerBeanDefinitions()方法
注册bean 定义
- 注册
AnnotationAwareAspectJAutoProxyCreator.class
,名称为“org.springframework.aop.config.internalAutoProxyCreator” - 如果我们设置EnableAspectJAutoProxy的两个属性,那么也将其注入BeanDefinition中
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
// 注册AspectJ相关的处理组件AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 为组件AnnotationAwareAspectJAutoProxyCreator添加属性
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
注册核心类的方法栈
三、postProcessBeforeInstantiation(实例化前寻找增强器并缓存)
- advisedBeans:map集合,key表示bean
名称
value表示bean是否需要被代理
- 如果一个bean的方法需要增强,那么这个 bean 就需要被代理来实现
- this.advisedBeans.put(cacheKey, Boolean.TRUE);(后面操作)
注解切面类
和切面接口相关类
Advice、Pointcut、Advisor、AopInfrastructureBean,不需要被代理- this.advisedBeans.put(cacheKey, Boolean.FALSE); (当前方法目的1)
- 如果一个bean的方法需要增强,那么这个 bean 就需要被代理来实现
- 将切面类所有的通知方法封装为Advisor增强器,缓存起来(当前方法目的2)
- 判断该类是否值自定义加强类型getCustomTargetSource(一般没有)
- 若是则加强执行包装操作返回代理对象
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
...
// 这个方法的主要目的就是在不考虑通知的情况下,确认哪些Bean不需要被代理
// 1.Advice,Advisor,Pointcut类型的Bean不需要被代理
// 2.不是原始Bean被包装过的Bean不需要被代理,例如ScopedProxyFactoryBean
// 实际上并不只是这些Bean不需要被代理,如果没有对应的通知需要被应用到这个Bean上的话
// 这个Bean也是不需要被代理的,只不过不是在这个方法中处理的。
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
// 如果beanName为空 或 没有为这个bean提供了定制的targetSource
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// advisedBeans是一个map,其中key是BeanName,value代表了这个Bean是否需要被代理
// 如果已经包含了这个key,不需要在进行判断了,直接返回即可
// 因为这个方法的目的就是在实例化前就确认哪些Bean是不需要进行AOP的
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 说明还没有对这个Bean进行处理
// 在这里会对SpringAOP中的基础设施bean,例如Advice,Pointcut,Advisor做标记
// 标志它们不需要被代理,对应的就是将其放入到advisedBeans中,value设置为false
// 其次,如果这个Bean不是最原始的Bean,那么也不进行代理,也将其value设置为false
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 是否为这个Bean提供了定制的TargetSource
// 如果提供了定制的TargetSource,那么直接在这一步创建一个代理对象并返回
// 一般不会提供
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;
}
1、isInfrastructureClass是否AspectJ基础类
- 子类重写父类方法isInfrastructureClass,又调用了父类方法
- 父类与子类方法满足其中一个即返回true,是AspectJ基础类
- 父类:当前 bean是否切面相关的类
Advice
、Pointcut
、Advisor
、AopInfrastructureBean
- 平常使用的注解,也可以使用接口实现
- 子类:当前 bean 是否切面(@Aspect注解的 bean)
- 父类:当前 bean是否切面相关的类
// 父类AbstractAutoProxyCreator方法
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
return retVal;
}
// 子类AnnotationAwareAspectJAutoProxyCreator方法
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null &&
this.aspectJAdvisorFactory.isAspect(beanClass)));
}
- @Aspect注解切面 bean 的判断
- 当前 bean 有
@Aspect
注解,并且没有使用ajc
编译器
// AbstractAspectJAdvisorFactory类的方法
@Override
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
// 当前 bean 是否找到注解Aspect
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
// 当前 bean 的属性值名字是否ajc$,就是判断是否使用 ajc 编译器
private boolean compiledByAjc(Class<?> clazz) {
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().startsWith(AJC_MAGIC)) {
return true;
}
}
return false;
}
2、shouldSkip是否跳过bean
- 看名字很简单,以为只是简单的判断
- 点进方法也简单,实际和上个方法逻辑一样,子类重写父类方法(主要逻辑在重写方法中)
- 先走子类方法,然后子类中调用父类的简单逻辑方法
// 子类AspectJAwareAdvisorAutoProxyCreator方法
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 查找所有候选的通知
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
/**
* 是 AspectJPointcutAdvisor 的子类 并且 切面名称是 beanName
* 一般是 InstantiationModelAwarePointcutAdvisorImpl
**/
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
- 父类方法:一般都是 false
- beanName的长度 = bean全限定类名+ .ORIGINAL(原始后缀)返回 true
// 父类AbstractAutoProxyCreator方法
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
2.1、findCandidateAdvisors查找增强器
- 老套路,先调用重写的子类,子类调用父类
// 子类AnnotationAwareAspectJAutoProxyCreator方法
@Override
protected List<Advisor> findCandidateAdvisors() {
// 获取Advisor子类增强器
List<Advisor> advisors = super.findCandidateAdvisors();
// 获取带有@AspectJ注解增强器
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
- 父类:把类型为Advisor的Bean都找出来处理,也就是通过接口实现AOP,我们一般使用注解,这里就是空
// 父类AbstractAdvisorAutoProxyCreator方法
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
buildAspectJAdvisors() 构建@AspectJ注解增强器
- 找到系统中使用
@Aspect
标注的bean - 并且找到该bean中使用
@Before
,@After
等标注的方法
- 将这些方法封装为一个个
Advisor
public List<Advisor> buildAspectJAdvisors() {
// 因为解析会很消耗性能,所以 Spring 会使用 aspectBeanNames 保存解析结果
List<String> aspectNames = this.aspectBeanNames;
// 如果==null 代表没处理过,因为第二次肯定不为 null,在 进入这个条件后,就会创建 ArrayList
if (aspectNames == null) {
// 进行加锁处理,防止多线程情况下一起操作解析
synchronized (this) {
// 二次赋值,防治以及操作过了
aspectNames = this.aspectBeanNames;
//双重非空判断,避免再次解析
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
// 创建切面集合
aspectNames = new ArrayList<>();
// 查找所有的 BeanName 包括父类
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
//排除不合法的ban,由子类定义规则,默认返回true
if (!isEligibleBean(beanName)) {
continue;
}
// 根据Name获取Class类型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 判断 是否存在 @Aspect 注解 并且判断 目标类上所有的属性不包含 "ajc$"
if (this.advisorFactory.isAspect(beanType)) {
// 将 切面的 BeanName 放入到集合中
aspectNames.add(beanName);
// 包装成 AspectMetadata
AspectMetadata amd = new AspectMetadata(beanType, beanName);
//检查 @Aspect 注解的value值,验证生成的增强是否是单例
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// 创建一个工厂..
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 获取标记 Aspect 注解的增强方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
//如果bean是单例,则缓存bean的增强器
if (this.beanFactory.isSingleton(beanName)) {
// 将 切面 BeanName 和 增强器 进行缓存
this.advisorsCache.put(beanName, classAdvisors);
}
// bean非单例,只缓存bean对应的增强器创建工厂
else {
this.aspectFactoryCache.put(beanName, factory);
}
// 将获取的 增强器 放入到集合中
advisors.addAll(classAdvisors);
}
else {
// 切面创建模式非单例,这里的Else 基本不会进来...
// 如果切面是非单例,但是bean是单例,抛出异常
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
//获取所有切面
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
//将已经解析过的切面 Bean 进行缓存
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
// 如果是 null 就会直接返回...
if (aspectNames.isEmpty()) {
// 如果是一个空的就返回一个空集合
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
// 循环 切面的Name
for (String aspectName : aspectNames) {
// 根据切面的Name 获取 增强器
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
// 返回~~~~
return advisors;
}
advisorFactory.getAdvisors 获取所有增强器
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 目标Aspect类
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 代理对象Bean的name
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 校验Aspect类上是不是标注了@Aspect注解
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//获取排除@Pointcut注解的其他方法
for (Method method : getAdvisorMethods(aspectClass)) {
//真正创建增强器
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 通过在装饰者内部的开始加入SyntheticInstantiationAdvisor增强器,达到延迟初始化切面bean的目的
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 对@DeclareParent注解功能的支持(引入)
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
获取排除@Pointcut注解的其他方法并排序
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
if (methods.size() > 1) {
methods.sort(adviceMethodComparator);
}
return methods;
}
getAdvisor 获取单个增强器
- 可以看出 Advisor 指的就是
切入点
和通知方法
的汇总
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 校验...
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 获取 切入点
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 在创建 InstantiationModelAwarePointcutAdvisorImpl 的时候
// 里面有一个 instantiateAdvice--> getAdvice 比较重要需要看一下
// 将切入点和通知包装成一个 增强器
return new InstantiationModelAwarePointcutAdvisorImpl(
expressionPointcut, //切入点表达式
candidateAdviceMethod, //通知方法
this,
aspectInstanceFactory, // 切面实例的工厂..
declarationOrderInAspect, //0
aspectName //切面名称
);
}
InstantiationModelAwarePointcutAdvisorImpl构造函数 创建具体通知
- 环绕通知增强器:AspectJAroundAdvice
- 实现
MethodInterceptor
接口,方法拦截器
- 实现
- 前置通知增强器:AspectJMethodBeforeAdvice
- 实现
MethodBeforeAdvice
接口,前置方法回调接口
- 实现
- 后置通知增强器:AspectJAfterAdvice
- 实现
MethodInterceptor
接口,方法拦截器
- 实现
- 返回通知增强器:AspectJAfterReturningAdvice
- 实现
AfterReturningAdvice
接口,前置方法回调接口 - 根据注解的属性值
returning
设置返回值参数名称
- 实现
- 异常通知增强器:AspectJAfterThrowingAdvice
- 实现
MethodInterceptor
接口,方法拦截器 - 根据注解的属性值
throwing
设置异常参数名称
- 实现
getAdvice() 生成不同通知实现类的方法
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName) {
//切面类 带有@Aspect注解的类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 获取通知方法的注解类型来确认当前方法是具体的那个类型的通知
// @Pointcut @Around @Before @After.class @AfterReturning @AfterThrowing
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//再去校验一遍 如果不是切面类 则抛出异常
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
AbstractAspectJAdvice springAdvice;
// 根据通知类型,创建不同的通知实例
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//如果是前置通知,则直接创建AspectJMethodBeforeAdvice实例
//入参为:通知方法、切点表达式、切面实例
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//如果是后置通知,则直接创建AspectJAfterAdvice实例
//入参为:通知方法、切点表达式、切面实例
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//如果是后置返回通知,则直接创建AspectJAfterReturningAdvice实例
//入参为:通知方法、切点表达式、切面实例
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
//设置后置返回值的参数name
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
//如果是后置异常通知,则直接创建AspectJAfterThrowingAdvice实例
//入参为:通知方法、切点表达式、切面实例
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
//设置后置异常通知 异常类型参数name
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// 切面的名字
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
// 通知注解中的参数名,换而言之就是获取 通知注解中的 argNames 属性
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
//计算argNames和类型的对应关系
springAdvice.calculateArgumentBindings();
return springAdvice;
}
总结
- 将不需要代理的切面类挑选出来
- 将切面的所有通知封装成增强器缓存起来
四、getEarlyBeanReference(循环依赖,提前暴露 bean)
- 如果出现循环依赖,需要提前暴露,这里创建代理对象并返回
- 将原始对象放入earlyProxyReferences,为了判断初始化后是否需要创建代理对象
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
五、postProcessAfterInitialization(初始化后创建代理对象)
- earlyProxyReferences如果有值(证明已经创建代理对象),remove 返回删除的对象,if 条件不成立,不再创建代理对象
- earlyProxyReferences没值(没有创建代理对象),remove 返回 null,if 条件成立,创建代理对象
@Override
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;
}
1、wrapIfNecessary(包装目标类,如果需要的话)
- advisedBeans这个map上面说过,key为bean名称,value为是否需要代理
- 如果当前bean的方法匹配任意切面任意通知,那么则此bean需要被代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 判断 beanName是正常的 并且 targetSourcedBeans已经存在则会直接返回(多例情况下)
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//判断 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.
// 创建代理对象
// 1. 获取当前Bean的所有增强器(通知方法)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果不是 null 则会去生成代理对象,否则则标记当前类不需要进行代理.
if (specificInterceptors != DO_NOT_PROXY) {
// 将其放入到集合当中代表已经增强过了...
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 2. 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 将数据进行缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理对象...
return proxy;
}
// 如果不需要代理则设置为 False 当下次进来的时候会直接返回
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
1.1、获取当前Bean的所有增强器
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//获取这个类型的所有增强器
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
// 如果是一个空的 则返回 一个空的 数组
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
// 将其转换成数组返回
return advisors.toArray();
}
- findCandidateAdvisors():获取所有切面类所有的通知方法封装为Advisor的增强器
- 实例化前已经获取,这里从缓存中获取即可
- findAdvisorsThatCanApply():获取当前bean能够应用的增强器
- 根据增强器的Pointcut表达式匹配当前bean的方法
- extendAdvisors():如果在该Bean上存在切面,创建ExposeInvocationInterceptor拦截器
- ExposeInvocationInterceptor类实现MethodInterceptor接口,方法拦截器
- 通过ThreadLocal暴露MethodInterceptor,调用链环节中直接获取
- sortAdvisors:主要作用不同切面的通知排序
- @Order注解的value属性指定各个切面的执行顺序,value值默认为Integer的最大值,value越小优先级越高
- 若两个或多个切面通过@Order注解标注且value值相同则又会通过默认的按bean名称字母排序
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取所有的增强器,这里之前已经分析过了就不分析了..
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//找到适合的增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 对增强器进行 排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
1.2、创建代理对象
代理工厂类图
创建代理工厂,添加创建代理需要的参数
- 代理的方式(jdk 或 cglib)
- 如果是jdk代理,添加需要实现的接口(目标对象实现的接口)
- 所有的增强器
- 目标对象
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();
// 将当前类的一些配置进行 复制 ,简单来说就是获取 XML 或者注解配置的属性
proxyFactory.copyFrom(this);
// 判断是否是通过接口 默认是 False
if (!proxyFactory.isProxyTargetClass()) {
// 根据最开始@EnableAspectJAutoProxy注解中的proxyTargetClass参数判断
// 是否应该使用cglib代理(默认jdk代理)
if (shouldProxyTargetClass(beanClass, beanName)) {
//标识 使用cglib动态代理
proxyFactory.setProxyTargetClass(true);
} else {
// 存在接口会将接口放入代理工厂
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 构建所有增强器(包括一个拦截器链)
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 放入到 代理工厂
proxyFactory.addAdvisors(advisors);
// 设置 目标 对象
proxyFactory.setTargetSource(targetSource);
// 留个子类去实现的一个方法,也就是说我们可以通过重写这个方法进行定制
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 获取代理对象【重要】
return proxyFactory.getProxy(getProxyClassLoader());
}
代理对象生成分析
- 通过ProxyFactory根据相应属性创建代理对象,首先创建
AopProxy
- 根据bean是否继承接口,生成
ObjenesisCglibAopProxy
或者JdkDynamicAopProxy
- 根据bean是否继承接口,生成
- 然后
getProxy
获取代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
// createAopProxy() 获取AOP 工厂判断 CGlib还是JDK
return createAopProxy().getProxy(classLoader);
}
createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 需要优化【默认为False】 或者 proxyTargetClass属性值为True【默认为False】 或者 没有用户提供的代理接口
if (config.isOptimize() || config.isProxyTargetClass()
|| hasNoUserSuppliedProxyInterfaces(config)) {
// 目标类
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException();
}
// 是接口 或者 类本身就是一个通过jdk动态代理生成的类
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// 使用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
// 使用 CGLIB 代理
return new ObjenesisCglibAopProxy(config);
}
// 默认使用 JDK 动态代理
else {
return new JdkDynamicAopProxy(config);
}
}
getProxy(jdk代理)
- Proxy.newProxyInstance(
classLoader
,proxiedInterfaces
,this
);- classLoader:类加载器
- proxiedInterfaces:代理对象需要实现的接口
- this:当前对象(其实是需要InvocationHandler的实现类,执行目标对象方法时,会触发它的的invoke方法)
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
...
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
// 这里获取到代理类需要实现的所有的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 需要明确是否在接口定义了hashCode以及equals方法
// 如果接口中没有定义,那么在调用代理对象的equals方法的时候
// 如果两个对象相等,那么意味着它们的目标对象,通知以及实现的接口都相同
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
...
}
获取到需要实现的接口
- 目标对象实现的接口
SpringProxy
:标记接口,代表这个类是通过Spring的AOP代理生成的Advised
,提供了管理通知的方法DecoratingProxy
,用于获取到真实的目标对象
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
// 第一步:获取在配置中指定的需要实现的接口
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
// 第二步:如果没有指定需要实现的接口,但是需要代理的目标类本身就是一个接口
// 那么将其添加到代理类需要实现的接口的集合中
// 如果目标类本身不是一个接口,但是是经过jdk代理后的一个类
// 那么获取这个代理后的类所有实现的接口,并添加到需要实现的接口集合中
if (specifiedInterfaces.length == 0) {
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
else if (Proxy.isProxyClass(targetClass)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
// 第三步:为代理类添加三个默认需要实现的接口,分别是
// 1.SpringProxy,一个标记接口,代表这个类是通过Spring的AOP代理生成的
// 2.Advised,提供了管理通知的方法
// 3.DecoratingProxy,用户获取到真实的目标对象
// 这个真实对象指的是在嵌套代理的情况下会获取到最终的目标对象
// 而不是指返回这个ProxyFactory的target
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
int nonUserIfcCount = 0;
if (addSpringProxy) {
nonUserIfcCount++;
}
if (addAdvised) {
nonUserIfcCount++;
}
if (addDecoratingProxy) {
nonUserIfcCount++;
}
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
int index = specifiedInterfaces.length;
if (addSpringProxy) {
proxiedInterfaces[index] = SpringProxy.class;
index++;
}
if (addAdvised) {
proxiedInterfaces[index] = Advised.class;
index++;
}
if (addDecoratingProxy) {
proxiedInterfaces[index] = DecoratingProxy.class;
}
return proxiedInterfaces;
}
1.3、处理器的invoke方法
- 目标对象是一个JDK
代理对象
,所以执行目标方法
会被上面实例化的JdkDynamicAopProxy代理对象的invoke()
方法拦截 - 如果当前方法匹配到增强器,则执行整个
拦截器链
(多个通知方法组成) - 如果当前方法没有匹配到增强器,则使用
反射
调用目标类方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 首先处理的是hashCode跟equals方法
// 如果接口中没有定义这两个方法,那么会调用本类中定义的equals方法
// 前面我们也说过了,只有当两个类的目标对象,通知以及实现的接口都相等的情况下
// equals才会返回true
// 如果接口中定义了这两个方法,那么最终会调用目标对象中的方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
// 也就是说我们调用的是DecoratingProxy这个接口中的方法
// 这个接口中只定义了一个getDecoratedClass方法,用于获取到
// 最终的目标对象,在方法实现中会通过一个while循环来不断接近
// 最终的目标对象,直到得到的目标对象不是一个被代理的对象才会返回
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 说明调用的是Advised接口中的方法,这里只是单纯的进行反射调用
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 说明需要将代理类暴露到线程上下文中
// 调用AopContext.setCurrentProxy方法将其放入到一个threadLocal中
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 接下来就是真正的执行代理逻辑了
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 先获取整个拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果没有进行拦截,直接反射调用方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
// 否则开始执行整个链条
else {
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
// 这里是处理一种特殊情况,就是当执行的方法返回值为this的情况
// 这种情况下,需要返回当前的代理对象而不是目标对象
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
获取拦截器链
- 先去缓存中获取,获取不到再进行复杂耗时的逻辑解析,然后放入缓存中,下次就直接获取到了
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method,
@Nullable Class<?> targetClass) {
// 目标对象方法的缓存键
// public abstract int com.xc.service.Calculate.add(int,int)
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 先去缓存中获取
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 缓存中没有,则进行逻辑解析
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
// 放入缓存中
this.methodCache.put(cacheKey, cached);
}
return cached;
}
- 获取当前bean所有的增强器,匹配当前
method
的增强器 - 将匹配到的Advisor(增强器)转化为方法拦截器(实现MethodInterceptor接口)
- 环绕通知、后置通知、异常通知已经实现MethodInterceptor接口,这里直接返回
前置通知
和返回通知
实现MethodInterceptor接口重新包装了一下
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
// 是否有引入通知
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 获取到所有的通知
for (Advisor advisor : config.getAdvisors()) {
// 除了引入通知外,可以认为所有的通知都是一个PointcutAdvisor
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// config.isPreFiltered:代表的是配置已经过滤好了,是可以直接应用的
// 这句代码的含义就是配置是预过滤的或者在类级别上是匹配的
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 接下来要判断在方法级别上是否匹配
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
// 将通知转换成对应的拦截器
// 有些通知本身就是拦截器,例如环绕通知
// 有些通知需要通过一个AdvisorAdapter来适配成对应的拦截器
// 例如前置通知,后置通知,异常通知等
// 其中MethodBeforeAdvice会被适配成MethodBeforeAdviceInterceptor
// AfterReturningAdvice会被适配成AfterReturningAdviceInterceptor
// ThrowAdvice会被适配成ThrowsAdviceInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 如果是动态的拦截,会创建一个InterceptorAndDynamicMethodMatcher
// 动态的拦截意味着需要根据具体的参数来决定是否进行拦截
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
// 说明是引入通知
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
// 前文我们有提到过,引入通知实际就是通过一个拦截器
// 将方法交由引入的类执行而不是目标类
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
// 可能会扩展出一些通知,一般不会
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
返回通知包装例子:
执行拦截器链
- ReflectiveMethodInvocation的proceed方法
- currentInterceptorIndex:当前拦截器链下标索引,从-1开始计算
- interceptorsAndDynamicMethodMatchers:拦截器链
public Object proceed() throws Throwable {
// 两者相等,证明已经 proceed 已经执行拦截器的总数量
// 满足这个条件,说明已经执行完了最后一个拦截器,那么直接反射调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取到下一个要执行的拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 前面构建拦截器链的时候我们可以看到,动态的拦截的话会创建一个InterceptorAndDynamicMethodMatcher
// 一般没有,不考虑
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
// 调用拦截器中的invoke方法,可以看到这里将this作为参数传入了
// 所以我们在拦截器中调用 MethodInvocation的proceed时又会进行入当前这个方法
// 然后去执行链条中的下一个拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
拦截器链顺序
- 根据切面类获取通知方法的时候,就给通知排序了,一直应用到拦截器链
- Around:环绕通知
- Before:前置通知
- After:后置(最终)通知
- AfterReturning:返回通知
- AfterThrowing:异常通知
- 在获取当前bean的增强器时候会添加一个ExposeInvocationInterceptor拦截器,放在最前面,第一个执行
注意:这只是拦截器执行顺序
2、各种拦截器作用
2.1、ExposeInvocationInterceptor默认拦截器
- 将MethodInvocation也就是ReflectiveMethodInvocation,放到本地线程ThreadLocal中
- ReflectiveMethodInvocation包含
拦截器链
、目标类
、当前执行方法和参数
- 后续的通知器里就可以根据
ExposeInvocationInterceptor.currentInvocation()
来得到ReflectiveMethodInvocation
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
...
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
public static MethodInvocation currentInvocation() throws IllegalStateException {
MethodInvocation mi = invocation.get();
return mi;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
...
}
2.2、AspectJAroundAdvice环绕通知拦截器
MethodInvocationProceedingJoinPoint类图
连接点对象
MethodInvocationProceedingJoinPoint- 内部维护MethodInvocation对象,即
ReflectiveMethodInvocation
对象
- 内部维护MethodInvocation对象,即
- 核心在于invokeAdviceMethod方法,此方法是父类AbstractAspectJAdvice中的方法,所有的通知对象都会继承此方法
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
// MethodInvocation对象,即ReflectiveMethodInvocation
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
// 创建连接点对象MethodInvocationProceedingJoinPoint,内部维护MethodInvocation对象
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
// 调用环绕通知方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
argBinding绑定参数
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
// 当前拦截器 returnValue(返回值)、t(异常)为空
// argBinding:绑定参数
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
protected Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable ex) {
// 解析参数,默认这里不需要再解析,前面创建Advisor的时候已经解析过一次了。
calculateArgumentBindings();
// 通知方法的参数
Object[] adviceInvocationArgs = new Object[this.parameterTypes.length];
int numBound = 0;
// 由于此方法是执行切面通知的通用方法,这里joinPointArgumentIndex一般是0
// 说明此方法参数为JoinPoint对象。具体类型是根据我们的通知方法的参数类型解析出来的。
if (this.joinPointArgumentIndex != -1) {
adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
numBound++;
}
else if (this.joinPointStaticPartArgumentIndex != -1) {
// 如果参数类型是JoinPoint.StaticPart,则给定此对象。一般我们不会给定此类型。
adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();
numBound++;
}
// argumentBindings一般是后置通知或最终通知以及异常通知。我们方法上给定参数对象的变量名。
// 满足上述条件才有会进入此if逻辑。
if (!CollectionUtils.isEmpty(this.argumentBindings)) {
// binding from pointcut match
// JoinPointMatch对象是前面从ProxyMethodInvocation中获取,一般我们不会设置,默认返回null。
if (jpMatch != null) {
PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();
for (PointcutParameter parameter : parameterBindings) {
String name = parameter.getName();
Integer index = this.argumentBindings.get(name);
adviceInvocationArgs[index] = parameter.getBinding();
numBound++;
}
}
// binding from returning clause
// 如果是目标方法执行后的通知,则可以获取它的返回值。
// 如果我们的通知方法参数给定了此返回值参数,这里就会进行返回值赋值。
if (this.returningName != null) {
Integer index = this.argumentBindings.get(this.returningName);
adviceInvocationArgs[index] = returnValue;
numBound++;
}
// binding from thrown exception
// 这里就是异常通知时,如果方法参数上指定,则进行异常对象赋值。
if (this.throwingName != null) {
Integer index = this.argumentBindings.get(this.throwingName);
adviceInvocationArgs[index] = ex;
numBound++;
}
}
if (numBound != this.parameterTypes.length) {
throw new IllegalStateException("Required to bind " + this.parameterTypes.length +
" arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
}
// 返回最终的参数对象数组。
return adviceInvocationArgs;
}
- 当执行
环绕通知
时,我们的通知方法参数只有ProceedingJoinPoint
对象 - 当执行其他通知时,参数也有ProceedingJoinPoint对象,但是只能用
父类对象JoinPoint
接收- 如果使用ProceedingJoinPoint对象接收,则解析@Aspect切面的通知创建通知对象时候抛出异常
- 另外idea也会提示错误,只有环绕通知可以使用ProceedingJoinPoint
- 如果使用ProceedingJoinPoint对象接收,则解析@Aspect切面的通知创建通知对象时候抛出异常
- 当执行
前置通知
和后置(最终)通知
时,通知方法参数只有JoinPoint
对象 - 当执行
返回通知
时,参数有JoinPoint
对象- 还会根据注解指定的返回参数变量名,给定对应的目标方法返回值
- 还会根据注解指定的返回参数变量名,给定对应的目标方法返回值
- 当执行
异常通知
时,参数有JoinPoint
对象- 还会根据注解指定的异常变量名称,给定对应的异常对象
- 还会根据注解指定的异常变量名称,给定对应的异常对象
反射执行通知方法
- 回到AspectJAroundAdvice环绕通知的拦截器
- aspectJAdviceMethod:切面类中的通知方法(这里是@Around注解的方法)
- 直接通过BeanFactory根据name获取bean
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
// 使给定的方法可访问
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// 反射调用增强处理方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
// 直接通过BeanFactory根据name获取bean
@Override
public Object getAspectInstance() {
return this.beanFactory.getBean(this.name);
}
进入环绕通知方法
通知方法的执行顺序
- Around—Before—目标方法—After—AfterReturning Or AfterThrowing
- 回到上面环绕通知方法,那么
joinPoint.proceed()
就是去执行其他通知方法和目标方法 - 进入joinPoint.proceed()的方法,其实就回到了jdk代理的invoke方法中的处理拦截器链
- 此时已经是第三次进入这个方法,最终会调用最后的
invoke
方法进入前置通知方法
2.3、MethodBeforeAdviceInterceptor前置通知拦截器
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
// 前置通知对象
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
// 先执行此前置通知的方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 调用下一个通知逻辑
return mi.proceed();
}
}
- 执行通用父类的通知执行逻辑,上面已经分析过了
- 组装JoinPoint对象参数,调用前置通知方法
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
// 执行通用父类的通知执行逻辑
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
- argNames就是设置注解方法的
参数名
,如果有多个,可以设置多个,用,隔开,一般不设置 - 执行完方法,回到上面的 mi.proceed(),再次回到ReflectiveMethodInvocation拦截器链,进入
后置(最终)通知
2.4、AspectJAfterAdvice后置(最终)通知拦截器
- mi.proceed():调用下一个通知逻辑,也就是返回通知
finally
里的invokeAdviceMethod:执行通用父类的通知执行逻辑,无论如何都会执行
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
}
- 返回通知或异常通知执行完,才会进入后置(最终)通知的方法
2.4、AspectJAfterAdvice返回通知拦截器
- mi.proceed():调用下一个通知逻辑,也就是异常通知
- advice.afterReturning:返回通知的逻辑
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
// 如果发生异常,则返回通知不执行,返回到异常通知逻辑,被捕获
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
2.5、AspectJAfterThrowingAdvice异常通知拦截器
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
...
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
private boolean shouldInvokeOnThrowing(Throwable ex) {
return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
}
}
- mi.proceed():回到拦截器链,会执行目标方法
- invokeAdviceMethod:执行通用父类的通知执行逻辑,组装参数,调用异常通知
3、总结通知执行顺序
没有异常情况
环绕通知(前) ➡️ 前置通知 ➡️ 目标方法 ➡️ 返回通知
➡️ 后置(最终通知) ➡️ 环绕通知(后)
有异常情况
环绕通知(前) ➡️ 前置通知 ➡️ 目标方法 ➡️ 异常通知
➡️ 后置(最终通知)