spring 中 AspectJ 基于注解的实现分析

ops/2025/2/12 22:25:16/

前面的文章介绍了 spring 引入 AspectJ 后,基于注解的 AOP 实现,今天我们来分析下这个实现的具体逻辑是怎么样的。

aspectj-autoproxy 解析

我们知道,基于注解的实现,在 xml 中除了需要配置切面类,还需要配置 aspecj 的自动代理。

<aop:aspectj-autoproxy/>

 我们先来看看这个标签的解析过程。

和以前自定义的标签解析过程一样,先去 spring-aop 模块下,META-INF/spring.handlers 下查看 aop 名命空间对应的处理器为 AopNamespaceHandler。在 AopNamespaceHandler#init 中注册的 aspectj-autoproxy 对应的解析器为 AspectJAutoProxyBeanDefinitionParser。

所以当解析到 <aop:aspectj-autoproxy> 标签时,就会使用 AspectJAutoProxyBeanDefinitionParser 去完成解析。

java">@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);// 是否扩展,即是否存在子标签,<aop:aspectj-autoproxy> 支持 <aop:include> 子标签extendBeanDefinition(element, parserContext);return null;
}
// AopNamespaceUtils
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {// 注册自动代理生成器,此处为 AnnotationAwareAspectJAutoProxyCreatorBeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));// 解析 proxy-target-class 和 expose-proxy 两个属性useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext);
}@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

也就是说,对 aspectj-autoproxy 的解析,其实就是注册了一个 AnnotationAwareAspectJAutoProxyCreator 自动代理生成器。

类结构

可以看到,这是一个 BeanPostProcessor,并且也实现了 SmartInstantiationAwareBeanPostProcessor,所以会在 bean 的实例化和初始化时发起调用。也可以看到,AnnotationAwareAspectJAutoProxyCreator 继承 AbstractAdvisorAutoProxyCreator 和 AbstractAutoProxyCreator,而这两个父类定义了 spring 中 AOP 实现的基本逻辑,可参考 spring 中自动代理生成器的实现。

AnnotationAwareAspectJAutoProxyCreator 注册

在 ApplicationContext 上下文容器启动时,会调用 AbstractApplicationContext#registerBeanPostProcessors 来对系统中注册的 BeanPostProcessor 进行实例化。也就是说,这个 AnnotationAwareAspectJAutoProxyCreator 实例对象就是在这个时候创建的。

从类结构可知,这个类实现了 BeanFactoryAware 接口,所以在初始化时会调用 invokeAwareMethods 为当前实例 bean 设置 beanFactory。

java">// AbstractAdvisorAutoProxyCreator
@Override
public void setBeanFactory(BeanFactory beanFactory) {super.setBeanFactory(beanFactory);if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);}initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
// AnnotationAwareAspectJAutoProxyCreator
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);// 给 aspectJAdvisorFactory 和 aspectJAdvisorsBuilder 赋值if (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}this.aspectJAdvisorsBuilder =new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}// 父类 AbstractAdvisorAutoProxyCreator
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}

可以看到,在这一步,实现了 AnnotationAwareAspectJAutoProxyCreator 中 aspectJAdvisorFactory 和 aspectJAdvisorsBuilder 的初始化赋值,也实现了 AbstractAdvisorAutoProxyCreator 中 advisorRetrievalHelper 的初始化。

之后,待 AnnotationAwareAspectJAutoProxyCreator 实例对象创建完成,将其注册到 AbstractBeanFactory 中的 beanPostProcessors。

代理的实现

Advisor 的创建

在业务 bean 的实例化创建过程中,由于注册了 AnnotationAwareAspectJAutoProxyCreator,会调用 AbstractAutoProxyCreator#postProcessBeforeInstantiation 来确定当前业务 bean 是否需要代理。

java">// AbstractAutoProxyCreator
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {if (this.advisedBeans.containsKey(cacheKey)) {return null;}// 确定当前 beanClass 是否不需要代理if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}// targetSource 不为 null,此处创建代理,一般 nullTargetSource 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;
}

其中 AnnotationAwareAspectJAutoProxyCreator 重写了 isInfrastructureClass 方法。

java">// AnnotationAwareAspectJAutoProxyCreator
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {return (super.isInfrastructureClass(beanClass) ||(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
// AbstractAutoProxyCreator
protected boolean isInfrastructureClass(Class<?> beanClass) {boolean retVal = Advice.class.isAssignableFrom(beanClass) ||Pointcut.class.isAssignableFrom(beanClass) ||Advisor.class.isAssignableFrom(beanClass) ||AopInfrastructureBean.class.isAssignableFrom(beanClass);if (retVal && logger.isTraceEnabled()) {logger.trace...}return retVal;
}

除了调用父类 AbstractAutoProxyCreator#isInfrastructureClass 之外,还增加了 this.aspectJAdvisorFactory.isAspect(beanClass) 的判断,而在 AnnotationAwareAspectJAutoProxyCreator 创建的初始化时已经完成了 aspectJAdvisorFactory 的初始化赋值。

从父类 AbstractAutoProxyCreator#isInfrastructureClass 可知,当业务类为 org.aopalliance.aop.Adviceorg.springframework.aop.Pointcutorg.springframework.aop.Advisor 和 org.springframework.aop.framework.AopInfrastructureBean 等接口的实现类时,是不需要代理的。而 AnnotationAwareAspectJAutoProxyCreator 也增加了一个条件,就是被 AspectJ 中的 @Aspect 注解修饰的业务类也是不需要代理的。

java">// AbstractAspectJAdvisorFactory
@Override
public boolean isAspect(Class<?> clazz) {// 判断是否持有 aspectj 中的 @Aspect 注解return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

假如 AnnotationAwareAspectJAutoProxyCreator#isInfrastructureClass 判断为 false,还需要进行 shouldSkip 的判断。父类 AspectJAwareAdvisorAutoProxyCreator 重写了 shouldSkip 方法

java">// AspectJAwareAdvisorAutoProxyCreator 重写了这个方法
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {// 寻找所有候选的 AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();for (Advisor advisor : candidateAdvisors) {if (advisor instanceof AspectJPointcutAdvisor &&((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {return true;}}return super.shouldSkip(beanClass, beanName);
}

接着 AnnotationAwareAspectJAutoProxyCreator 重写了 findCandidateAdvisors 方法。

java">// AnnotationAwareAspectJAutoProxyCreator
@Override
protected List<Advisor> findCandidateAdvisors() {// 添加根据父类规则找到的所有 Spring advisorsList<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// 利用 aspectJAdvisorsBuilder 构建 aspectj 形式的 Advisorif (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;
}

获取 BeanFactory 中定义的所有 Advisor,由两部分组成,一部分是实现了 spring 中 Advisor 接口的 Advisor 子类实例对象,一部分是利用 AnnotationAwareAspectJAutoProxyCreator 中的 aspectJAdvisorsBuilder 构建出 beanFactory 中注册的所有 aspectj 形式的 Advisor。

下面我们主要来看下 aspectj 形式的 Advisor 的获取过程。

java">// BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {List<String> aspectNames = this.aspectBeanNames;if (aspectNames == null) {synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {List<Advisor> advisors = new ArrayList<>();aspectNames = new ArrayList<>();String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}// We must be careful not to instantiate beans eagerly as in this case they// would be cached by the Spring container but would not have been weaved.Class<?> beanType = this.beanFactory.getType(beanName, false);if (beanType == null) {continue;}if (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);AspectMetadata amd = new AspectMetadata(beanType, beanName);if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);if (this.beanFactory.isSingleton(beanName)) {this.advisorsCache.put(beanName, classAdvisors);}else {this.aspectFactoryCache.put(beanName, factory);}advisors.addAll(classAdvisors);}else {// Per target or per this.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));}}}this.aspectBeanNames = aspectNames;return advisors;}}}if (aspectNames.isEmpty()) {return Collections.emptyList();}List<Advisor> advisors = new ArrayList<>();for (String aspectName : aspectNames) {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;
}public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, @Nullable Class<?> type) {Assert.notNull(beanFactory, "BeanFactory must not be null");Assert.notNull(name, "Bean name must not be null");this.beanFactory = beanFactory;this.name = name;Class<?> resolvedType = type;if (type == null) {resolvedType = beanFactory.getType(name);Assert.notNull(resolvedType, "Unresolvable bean type - explicitly specify the aspect class");}this.aspectMetadata = new AspectMetadata(resolvedType, name);
}

实现逻辑如下:

  1. 获取 beanFactory 中注册的所有 beanName,包含手动注册的内部类
  2. 遍历获取到的 beanNames 数组,此处,如果配置了 <aop:include> 子标签,会调用 isEligibleBean 对 beanName 进行正则匹配
  3. 根据 beanName,获取具体的 Class 类型,判断是否是 @Aspect 修饰的切面类,只有是@Aspect 切面类,才会进行操作
  4. 创建一个 AspectMetadata 对象,创建的过程中会创建一个 AjTypeImpl 为 AspectMetadata 中的 ajType 赋值,@Aspect 中的 value 值决定了切面的实例化模型,默认 "",代表类型为 PerClauseKind.SINGLETON
  5. 创建一个切面实例工厂,即 BeanFactoryAspectInstanceFactory 对象,接着利用 this.advisorFactory.getAdvisors(factory) 获取当前切面类中定义的所有顾问,而这个 advisorFactory 就是在 AnnotationAwareAspectJAutoProxyCreator 初始化时创建的 ReflectiveAspectJAdvisorFactory 对象
  6. 对获取到的 Advisor 集合进行缓存 

这是整个 beanFactory 中 aspectj 形式的 Advisor 的获取,具体到某一个 Class,我们接着向下看。

java">// ReflectiveAspectjAdvisorFactory
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {// BeanFactoryAspectInstanceFactory// 获取 aspectClassClass<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();// 获取注册的切面 beanNameString aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();validate(aspectClass);// 二次包装MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);List<Advisor> advisors = new ArrayList<>();for (Method method : getAdvisorMethods(aspectClass)) {// 将一个 method 封装为一个 AdvisorAdvisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);if (advisor != null) {advisors.add(advisor);}}// advisors 不为空,isLazilyInstantiated 判断为 falseif (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);advisors.add(0, instantiationAdvisor);}// Find introduction fields.for (Field field : aspectClass.getDeclaredFields()) {Advisor advisor = getDeclareParentsAdvisor(field);if (advisor != null) {advisors.add(advisor);}}return advisors;
}

 核心逻辑就是获取 aspectClass 中的切面方法,封装 Advisor。先来看获取切面方法的实现。

java">// ReflectiveAspectJAdvisorFactory
// 获取切面类中的切面方法
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;
}// ReflectiveAspectJAdvisorFactory
// 过滤条件,必须是自定义方法,且不是切入点,即不持有 @Pointcut 注解
private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));// ReflectionUtils
public static final MethodFilter USER_DECLARED_METHODS =(method -> !method.isBridge() && !method.isSynthetic() && (method.getDeclaringClass() != Object.class));// ReflectionUtils
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {if (mf == USER_DECLARED_METHODS && clazz == Object.class) {return;}// clazz 定义方法,包括接口默认方法Method[] methods = getDeclaredMethods(clazz, false);for (Method method : methods) {// 不满足过滤条件,进行下一次循环if (mf != null && !mf.matches(method)) {continue;}// 满足条件,执行回调,其实就是加入集合,执行 methods::addtry {mc.doWith(method);}catch (IllegalAccessException ex) {throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);}}// 处理父类if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {doWithMethods(clazz.getSuperclass(), mc, mf);}else if (clazz.isInterface()) {for (Class<?> superIfc : clazz.getInterfaces()) {doWithMethods(superIfc, mc, mf);}}
}// org.springframework.util.ReflectionUtils.MethodFilter
default MethodFilter and(MethodFilter next) {Assert.notNull(next, "Next MethodFilter must not be null");return method -> matches(method) && next.matches(method);
}

过滤条件 adviceMethodFilter,用户自定义的方法,且不持有 @Pointcut 注解。此处处理的方法不仅包括自己类中的,也包含父类中的。获取到切面方法之后,封装 Advisor。

java">// ReflectiveAspectJAdvisorFactory
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName) {validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());// 利用切面方法和其上的注解,封装一个 AspectJExpressionPointcut// 获取切入点表达式,不存在,返回 null,表示不存在 AdvisorAspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());if (expressionPointcut == null) {return null;}return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

首先,会利用切面方法和方法上的注解,封装一个 AspectJExpressionPointcut,此处,如果不存在切点表达式,直接返回 null。也就是说,aspectj 的核心就是这个切点表达式

java">// ReflectiveAspectJAdvisorFactory
// 封装 AspectJExpressionPointcut
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {// 获取切面方法上 aspectj 中定义的通知注解AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}// 创建 AspectJExpressionPointcutAspectJExpressionPointcut ajexp =new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);ajexp.setExpression(aspectJAnnotation.getPointcutExpression());if (this.beanFactory != null) {// 为 AspectJExpressionPointcut 设置 beanFactoryajexp.setBeanFactory(this.beanFactory);}return ajexp;
}
// AbstractAspectJAdvisorFactory
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {// ASPECTJ_ANNOTATION_CLASSES 6 个// @Pointcut/@Around/@Before/@After/@AfterReturning/@AfterThrowingfor (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);if (foundAnnotation != null) {return foundAnnotation;}}return null;
}
// 获取 AspectJAnnotation
@Nullable
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {A result = AnnotationUtils.findAnnotation(method, toLookFor);if (result != null) {return new AspectJAnnotation<>(result);}else {return null;}
}

遍历 aspectj 中通知类型对应的注解,判断当前切面类方法上是否持有某一个注解,找到了就封装成 AspectJAnnotation。遍历的 ASPECTJ_ANNOTATION_CLASSES 包含 @Pointcut,但前边过滤切面方法的时候排除了 @Pointcut 修饰的方法,所以此处查找 @Pointcut 恒为 null。

java">public AspectJAnnotation(A annotation) {this.annotation = annotation;this.annotationType = determineAnnotationType(annotation);try {// 解析切入点表达式,得到配置的字符串this.pointcutExpression = resolveExpression(annotation);// 参数名称,注解 argNames 属性Object argNames = AnnotationUtils.getValue(annotation, "argNames");this.argumentNames = (argNames instanceof String ? (String) argNames : "");}catch (Exception ex) {throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);}
}
// AbstractAspectJAdvisorFactory.AspectJAnnotation
private String resolveExpression(A annotation) {// EXPRESSION_ATTRIBUTES 共包含两个,pointcut 和 valuefor (String attributeName : EXPRESSION_ATTRIBUTES) {// 反射获取注解对应属性值Object val = AnnotationUtils.getValue(annotation, attributeName);if (val instanceof String) {String str = (String) val;if (!str.isEmpty()) {return str;}}}throw new IllegalStateException("Failed to resolve expression: " + annotation);
}

解析注解值,得到切点表达式,就是配置的字符串,封装的 AspectJAnnotation 包含了注解的所有信息。

接着创建 AspectJExpressionPointcut 对象,为其设置 expression 和 beanFactory。之后,创建一个 InstantiationModelAwarePointcutAdvisorImpl 对象,就是最终需要的 Advisor 对象。

java">public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {this.declaredPointcut = declaredPointcut;this.declaringClass = aspectJAdviceMethod.getDeclaringClass();// 方法名称this.methodName = aspectJAdviceMethod.getName();// 切面方法参数类型this.parameterTypes = aspectJAdviceMethod.getParameterTypes();this.aspectJAdviceMethod = aspectJAdviceMethod;this.aspectJAdvisorFactory = aspectJAdvisorFactory;this.aspectInstanceFactory = aspectInstanceFactory;this.declarationOrder = declarationOrder;this.aspectName = aspectName;// falseif (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {// Static part of the pointcut is a lazy type.Pointcut preInstantiationPointcut = Pointcuts.union(aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.// If it's not a dynamic pointcut, it may be optimized out// by the Spring AOP infrastructure after the first evaluation.this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);this.lazy = true;}else {// A singleton aspect.this.pointcut = this.declaredPointcut;this.lazy = false;// Advisor 需要 Advice,此处实例化通知this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);}
}

isLazilyInstantiated() 会返回 false,执行 else 代码块。

java">private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {// aspectJAdvisorFactory  ReflectiveAspectJAdvisorFactoryAdvice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,this.aspectInstanceFactory, this.declarationOrder, this.aspectName);return (advice != null ? advice : EMPTY_ADVICE);
}// ReflectiveAspectJAdvisorFactory
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {// 获取切面类Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();validate(candidateAspectClass);// 创建 AspectJAnnotationAspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}// candidateAspectClass 上持有注解 @Aspectif (!isAspect(candidateAspectClass)) {throw new AopConfigException("Advice must be declared inside an aspect type: " +"Offending method '" + candidateAdviceMethod + "' in class [" +candidateAspectClass.getName() + "]");}if (logger.isDebugEnabled()) {logger.debug("Found AspectJ method: " + candidateAdviceMethod);}AbstractAspectJAdvice springAdvice;// 通知类型到 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;case AtBefore:springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfter:springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfterReturning:springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();// 后置通知注解存在 returning 属性if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}break;case AtAfterThrowing:springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();// 异常通知注解存在 throwing 属性if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {springAdvice.setThrowingName(afterThrowingAnnotation.throwing());}break;default:throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}// 配置 advicespringAdvice.setAspectName(aspectName);// 0springAdvice.setDeclarationOrder(declarationOrder);// 获取注解上对应 argNames 属性String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}// 参数绑定springAdvice.calculateArgumentBindings();return springAdvice;
}

在 ReflectiveAspectJAdvisorFactory#getAdvice 完成切面方法到 spring 中 Advice 的转换。以 @Before 为例,对应 AspectJMethodBeforeAdvice。

java">public AspectJMethodBeforeAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {super(aspectJBeforeAdviceMethod, pointcut, aif);
}public AbstractAspectJAdvice(Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");this.declaringClass = aspectJAdviceMethod.getDeclaringClass();this.methodName = aspectJAdviceMethod.getName();this.parameterTypes = aspectJAdviceMethod.getParameterTypes();this.aspectJAdviceMethod = aspectJAdviceMethod;this.pointcut = pointcut;this.aspectInstanceFactory = aspectInstanceFactory;
}

所有的 AspectJXXXAdvice 都继承 AbstractAspectJAdvice,实现 spring 中定义的通知接口。也就是说,将 AspectJ 中的通知方法封装成了 spring 中的通知。实现了 Advisor 中 Advice 的统一,为之后方法调用获取拦截器链时的统一适配做准备。

spring 中实现 AOP 时定义的通知接口如下:

  • 前置通知  org.springframework.aop.MethodBeforeAdvice
  • 后置通知  org.springframework.aop.AfterReturningAdvice
  • 环绕通知  org.aopalliance.intercept.MethodInterceptor
  • 异常通知  org.springframework.aop.ThrowsAdvice

AspectJ 中多了一种通知类型,最终通知,其实现的接口为 org.aopalliance.intercept.MethodInterceptor,还有一点,就是异常通知,实现的接口也是  org.aopalliance.intercept.MethodInterceptor,通过 try...catch 来捕获异常,调用切面方法。

此时已经完成了 Advisor 的创建,其实就是将 @Aspect 修饰的类中定义的 AspectJ 类型的通知方法封装为 InstantiationModelAwarePointcutAdvisorImpl,一个通知方法对应一个 Advisor。

为切面类创建完所有的 Advisor 之后,再回到 AspectJAwareAdvisorAutoProxyCreator#shouldSkip 方法,这个 InstantiationModelAwarePointcutAdvisorImpl 不是 AspectJPointcutAdvisor 子类,调用父类的 shouldSkip 来判断是否需要跳过。

java">// AbstractAutoProxyCreator 
protected boolean shouldSkip(Class<?> beanClass, String beanName) {return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {// ORIGINAL_INSTANCE_SUFFIX  ".ORIGINAL"if (!StringUtils.hasLength(beanName) || beanName.length() !=beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {return false;}return (beanName.startsWith(beanClass.getName()) &&beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
}

从这个实现来看,基本上都会返回 false,也就是不跳过。所以这个判断主要还靠第一个 isInfrastructureClass,但是在第二个判断 shouldSkip 中,注解模式下已经完成了  Advisor 的创建。

代理的创建

在用户业务类实例化对象初始化的过程中,会执行AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization,集中处理 BeanPostProcessor,由于注册了 AnnotationAwareAspectJAutoProxyCreator,进而就会执行 AbstractAutoProxyCreator#postProcessAfterInitialization

java">@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;
}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// 如果不需要代理,在 AbstractAutoProxyCreator#postProcessBeforeInstantiation 会填充 falseif (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;}// 创建代理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;
}

我们知道,这是 spring 中创建代理的模板方法。

此时在调用 shouldSkip 进行是否需要代理的判断时,在 BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors 中,aspectNames 不为 null,从缓存获取 advisors,不需要跳过,开始代理的创建。

java">// AbstractAdvisorAutoProxyCreator
@Override
@Nullable
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();
}protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 调用子类方法获取候选 Advisor,即系统中所有切面类中方法所创建的 AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 过滤List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);// 扩展 Advisor,在 Advisor 集合最前面添加一个 ExposeInvocationInterceptor.ADVISORextendAdvisors(eligibleAdvisors);// 不为空,进行排序if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;
}// AnnotationAwareAspectJAutoProxyCreator
@Override
protected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;
}

在 AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 方法中,findCandidateAdvisors 会调用子类重写的方法,此处为 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors,会从 BeanFactoryAspectJAdvisorsBuilder 中 advisorsCache 缓存获取到所有 Advisor,接着利用规则对其进行过滤,选出和当前业务类中方法相匹配的 Advisor。

java">// AbstractAdvisorAutoProxyCreator
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}
}
// AopUtils
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new ArrayList<>();for (Advisor candidate : candidateAdvisors) {// 不是 IntroductionAdvisor 子类if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// 已经处理过了,跳过continue;}if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;
}public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}// 是 PointcutAdvisor 子类else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;// pca.getPointcut() 返回 AspectJExpressionPointcutreturn canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}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.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for (Class<?> clazz : classes) {// 获取 clazz 上定义的所有方法,包含接口上 default 方法和 Object 中定义的方法Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :methodMatcher.matches(method, targetClass)) {return true;}}}return false;
}

最终通过 AopUtils#canApply 来判断候选的当前 Advisor 是否可用,此处的 Pointcut 为 org.springframework.aop.aspectj.AspectJExpressionPointcut,这是一个连接 spring 与 AspectJ 的中间类,类似于一个桥梁,一头连着 spring,另一头连着 AspectJ,将具体的切入点表达式的解析以及是否为切入点方法的判断都委托给 AspectJ 去实现,而代理的处理过程依然遵循 spring 中定义的实现模板。

java">// AspectJExpressionPointcut
@Override
public ClassFilter getClassFilter() {obtainPointcutExpression();return this;
}
private PointcutExpression obtainPointcutExpression() {if (getExpression() == null) {throw new IllegalStateException("Must set property 'expression' before attempting to match");}if (this.pointcutExpression == null) {// 获取 ClassLoaderthis.pointcutClassLoader = determinePointcutClassLoader();this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);}// PointcutExpressionImplreturn this.pointcutExpression;
}

创建了一个 org.aspectj.weaver.internal.tools.PointcutExpressionImpl,赋值给 AspectJExpressionPointcut 中的 pointcutExpression。此后 AspectJ 中的所有操作都是通过这个 pointcutExpression 来发起。

AspectJExpressionPointcut 既实现了 ClassFilter 接口,又实现了 MethodMatcher 接口,但所有的匹配都是委托给 pointcutExpression 来操作,所以第一步都是调用 AspectJExpressionPointcut#obtainPointcutExpression 方法来获取 pointcutExpression。

针对 ClassFilter,默认 true,所以具体的匹配主要在方法上。

接下来来看具体的方法匹配。调用 ReflectionUtils.getAllDeclaredMethods(clazz) 获取 clazz 上定义的所有方法,包括 clazz 自己定义的方法以及实现接口中定义的 default 方法、Object 类中定义的方法。之后遍历每一个方法,调用 AspectJExpressionPointcut#matches 进行匹配,所以这实际上是一个比较耗时的操作。

当业务类中存在和切入点表达式匹配的方法时,canApply 返回 true,将候选的 Advisor 加入 eligibleAdvisors,然后将符合条件的 Advisor 集合返回。

再回到 AbstractAutoProxyCreator#wrapIfNecessary 中,将上面返回的 Advisor 集合赋值给 specificInterceptors。

接下来进入 AbstractAutoProxyCreator#createProxy 开始代理的创建。

java">// AbstractAutoProxyCreator
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);}// AdvisedSupport 子类ProxyFactory proxyFactory = new ProxyFactory();// 此时 this 为 AnnotationAwareAspectJAutoProxyCreatorproxyFactory.copyFrom(this);// <aop:aspectj-autoproxy/> 标签属性 proxy-target-classif (proxyFactory.isProxyTargetClass()) {// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.for (Class<?> ifc : beanClass.getInterfaces()) {proxyFactory.addInterface(ifc);}}}else {// No proxyTargetClass flag enforced, let's apply our default checks...if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {// 未设置属性 proxy-target-class,评估目标类是否存在接口,存在接口则为 proxyFactory 进行设置,不存在接口默认设置 setProxyTargetClass 为 trueevaluateProxyInterfaces(beanClass, proxyFactory);}}// 获取 Advisor,针对非 AspectJ 类型的自动代理生成器Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);// 已经过滤过了if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// Use original ClassLoader if bean class not locally loaded in overriding class loaderClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}return proxyFactory.getProxy(classLoader);
}

我们知道,这是 spring 中创建代理的模板方法。具体可参考 spring 中自动代理生成器的实现。

JdkDynamicAopProxy 和 CglibAopProxy 都持有一个 AdvisedSupport,在创建 DynamicAdvisedInterceptor 时又通过构造方法把这个 AdvisedSupport 传递给了 DynamicAdvisedInterceptor。

在 AbstractAutoProxyCreator#createProxy 方法中,可以看到,这个 AdvisedSupport 就是 org.springframework.aop.framework.ProxyFactory。

ProxyConfig 定义了代理的一些相关属性,例如:控制采用哪种代理方式的 proxyTargetClass 和 optimize。

在 ProxyCreatorSupport 的无参构造方法中,创建了一个 DefaultAopProxyFactory 对象,为 aopProxyFactory 字段赋值,创建代理就是通过 DefaultAopProxyFactory#createAopProxy 方法来实现的。

顺便说下,在标签 <aop:aspectj-autoproxy/> 中设置 proxy-target-class 属性来控制采用哪种代理方式,最后就是传递给了 ProxyConfig 中的 proxyTargetClass 字段。如果未指定,目标类存在接口,默认 JdkDynamicAopProxy 代理,如果不存在接口,默认会将 proxyTargetClass 设置为 true,之后采用 ObjenesisCglibAopProxy 代理。

到这里,spring 中 AspectJ 基于注解的代理创建就已经完成了,可以看到 spring 提供了优秀的设计来方便扩展,最终实现了代理创建的统一。

方法调用

我们知道,创建的代理有两种类型,一种是 JdkDynamicAopProxy,一种是 ObjenesisCglibAopProxy。

JdkDynamicAopProxy 实现了 java.lang.reflect.InvocationHandler 接口,发起调用时,会调用 invoke 方法。

ObjenesisCglibAopProxy,通过为 Cglib 创建的代理对象设置 Callbacks 属性,发起调用时,会调用 intercept 方法。

org.springframework.cglib.proxy.Callback 是一个标识接口,并无具体的接口方法,org.springframework.cglib.proxy.MethodInterceptor 继承  org.springframework.cglib.proxy.Callback,在 MethodInterceptor 中定义了拦截方法。通用的实现类,即 org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor,这是一个存在于 CglibAopProxy 中的内部类。 

不管是 JdkDynamicAopProxy#invoke,还是 DynamicAdvisedInterceptor#intercept,核心实现逻辑基本相同:

  1. 获取指定 method 对应的拦截器链;
  2. 创建相应的 org.aopalliance.intercept.MethodInvocation;
  3. 执行方法调用。

首先来看获取指定 method 对应的拦截器链,其实为目标类创建代理的时候,已经筛选出了目标类对应的 Advisor,通过 ProxyFactory 传递给 AdvisedSupport,此处再次进行筛选,是为了找出符合当前调用的目标方法的 Advisor

接着创建方法调用,JdkDynamicAopProxy 创建的是 ReflectiveMethodInvocation,CglibAopProxy 创建的是 CglibMethodInvocation。二者并无区别,CglibMethodInvocation 是 ReflectiveMethodInvocation 的子类,只是多了一个 org.springframework.cglib.proxy.MethodProxy 字段,用来发起对目标方法的调用。

java">@Override
protected Object invokeJoinpoint() throws Throwable {if (this.methodProxy != null) {try {return this.methodProxy.invoke(this.target, this.arguments);}catch (CodeGenerationException ex) {logFastClassGenerationFailure(this.method);}}return super.invokeJoinpoint();
}

需要注意的是,这里有两个 MethodInterceptor,分别位于不同的包下。

全类名作用
org.aopalliance.intercept.MethodInterceptor作为拦截器存在,spring 中的环绕通知接口,所有的 Advisor,在方法调用封装拦截器链时,会被适配成 org.aopalliance.intercept.MethodInterceptor
org.springframework.cglib.proxy.MethodInterceptor

继承 org.springframework.cglib.proxy.Callback,作为 Cglib 回调存在,常用实现类 

org.springframework.aop.framework.CglibAopProxy

.DynamicAdvisedInterceptor,Cglib 代理对象发起目标方法调用时,会执行相应的接口实现类方法

下面我们来看一个问题,就是 AspectJ 对 AOP 的实现时,为什么要在所有 Advisor 之前,加入一个 ExposeInvocationInterceptor.ADVISOR?

执行方法调用时,先调入第一个拦截器,即 ExposeInvocationInterceptor.ADVISOR。

java">// ExposeInvocationInterceptor
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {// invocation 是一个 ThreadLocalMethodInvocation oldInvocation = invocation.get();invocation.set(mi);try {return mi.proceed();}finally {invocation.set(oldInvocation);}
}

将当前 MethodInvocation 写入 ThreadLocal,接着就调入了下一个拦截器。

此处以前置通知封装成的 MethodBeforeAdviceInterceptor 为例。

java">// MethodBeforeAdviceInterceptor
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());return mi.proceed();
}// AspectJMethodBeforeAdvice
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {invokeAdviceMethod(getJoinPointMatch(), null, null);
}

这些 AspectJXXXAdvice 最终都是调用父类 AbstractAspectJAdvice#invokeAdviceMethod 方法。

java">// AbstractAspectJAdvice
protected Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)throws Throwable {return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}

先执行 getJoinPoint 方法,接着执行 argBinding 方法。

java">// AbstractAspectJAdvice
protected JoinPoint getJoinPoint() {return currentJoinPoint();
}
public static JoinPoint currentJoinPoint() {MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();if (!(mi instanceof ProxyMethodInvocation)) {throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);}ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);if (jp == null) {// 创建 JoinPoint 实现类jp = new MethodInvocationProceedingJoinPoint(pmi);pmi.setUserAttribute(JOIN_POINT_KEY, jp);}return jp;
}// ReflectiveMethodInvocation
@Override
public void setUserAttribute(String key, @Nullable Object value) {if (value != null) {if (this.userAttributes == null) {this.userAttributes = new HashMap<>();}// 键值对this.userAttributes.put(key, value);}else {if (this.userAttributes != null) {this.userAttributes.remove(key);}}
}

创建了一个 MethodInvocationProceedingJoinPoint 对象。

java">// AbstractAspectJAdvice
// 参数绑定
protected Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch,@Nullable Object returnValue, @Nullable Throwable ex) {// 处理参数绑定索引calculateArgumentBindings();// AMC startObject[] adviceInvocationArgs = new Object[this.parameterTypes.length];int numBound = 0;// joinPointArgumentIndex// ReflectiveAspectJAdvisorFactory#getAdvice 封装 springAdvice 时由于调用过 calculateArgumentBindings,造成 joinPointArgumentIndex 已修改if (this.joinPointArgumentIndex != -1) {adviceInvocationArgs[this.joinPointArgumentIndex] = jp;numBound++;}else if (this.joinPointStaticPartArgumentIndex != -1) {adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();numBound++;}// argumentBindings 不为空时,根据名称确定索引,之后为 adviceInvocationArgs 数组赋值if (!CollectionUtils.isEmpty(this.argumentBindings)) {// binding from pointcut matchif (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 clauseif (this.returningName != null) {Integer index = this.argumentBindings.get(this.returningName);adviceInvocationArgs[index] = returnValue;numBound++;}// binding from thrown exceptionif (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;
}protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {Object[] actualArgs = args;if (this.aspectJAdviceMethod.getParameterCount() == 0) {actualArgs = null;}try {ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);// 反射调用切面类中的通知方法,传入 actualArgs 即为参数绑定后的实际值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();}
}

 也就是说,在 argBinding 方法中完成了通知方法的参数封装,为切面类中通知方法的调用做好了准备。

现在再来说为什么需要一个 ExposeInvocationInterceptor.ADVISOR,其实就是为了将当前的方法调用写入 ThreadLocal,每个方法调用传入的参数可能不同,通过 ThreadLocal 实现了数据间的隔离,避免了数据污染。

接着,也引出了 AspectJ 中另一个知识,就是 @Aspect 修饰下的切面类中的通知方法,是可以携带参数的。@Before 前置通知方法可以携带 JoinPoint,@AfterReturning 后置通知注解有 returning 属性,一般将通知方法参数类型定义为 Object,因为目标
方法的返回值可以是任意类型,@Around 环绕通知可以携带 ProceedingJoinPoint,@AfterThrowing 异常通知注解中有 throwing 属性,通知方法参数类型为 Throwable。

总结

总结一下,就是代理实现时,会将 @AspectJ 中的通知方法封装为 spring 中定义的 Advisor, 一个方法对应一个 Advisor,同时将通知方法适配为 spring 中的通知类型,被 Advisor 所持有。在方法调用时,由 springspring 中的通知类型统一适配为 org.aopalliance.intercept.MethodInterceptor,也就是拦截器,之后按顺序逐个执行。

spring 引入 AspectJ,其实是在 AspectJ 之上做的二次开发,来适配自己定义的 AOP 实现逻辑。

 


http://www.ppmy.cn/ops/157067.html

相关文章

使用rustDesk搭建私有远程桌面

一、rustDesk官方网站 RustDesk – 开源远程桌面访问软件 二、下载地址 客户端&#xff1a;https://github.com/rustdesk/rustdesk/releases/tag/1.2.7 服务端&#xff1a;https://github.com/rustdesk/rustdesk-server/releases/tag/1.1.11-1 三、服务端安装&#xff08;…

Visual Basic语言的区块链

Visual Basic语言与区块链技术的结合 引言 在当今数字化迅猛发展的时代&#xff0c;区块链技术以其去中心化、安全性和透明性等特点&#xff0c;逐渐成为各行各业的重要解决方案。与此同时&#xff0c;作为一种古老而经典的编程语言&#xff0c;Visual Basic&#xff08;VB&a…

RISCV基础知识

一、ISA指令集 ISA 命名格式&#xff1a;RV [###] [abc…xyz] RV&#xff1a;用于标识 RISC-V体系架构的前缀&#xff0c;既 RISC-V 的缩写。 [###] &#xff1a;{32, 64, 128} 用于标识处理器的字宽&#xff0c;也就是处理器的寄存器的宽度&#xff08;单位为bit&#xff0…

wordpressAI工具,已接入Deepseek 支持自动生成文章、生成图片、生成长尾关键词、前端AI窗口互动、批量采集等

基于关键词或现有内容生成SEO优化的文章&#xff0c;支持多种AI服务&#xff08;如OpenAI、百度文心一言、智谱AI等&#xff09;&#xff0c;并提供定时任务、内容采集、关键词生成等功能。 核心功能 文章生成 关键词生成&#xff1a;根据输入的关键词生成高质量文章。 内容…

亚博microros小车-原生ubuntu支持系列:24 巡线驾驶

这篇跟之前的颜色识别类似&#xff0c;亚博microros小车-原生ubuntu支持系列&#xff1a;21 颜色追踪-CSDN博客 1、程序功能说明 程序启动后&#xff0c;调整摄像头的俯仰角&#xff0c;把摄像头往下掰动&#xff0c;使得摄像头可以看到线&#xff0c;然后点击图像窗口&#…

【MySQL系列】记插入产生的死锁问题

???欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老…

DeepSeek R1本地化部署 Ollama + Chatbox 打造最强 AI 工具

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; Ollama &#x1f98b; 下载 Ollama&#x1f98b; 选择模型&#x1f98b; 运行模型&#x1f98b; 使用 && 测试 二&#xff1a;&#x1f525; Chat…

?和.和*在正则表达式里面的区别

在正则表达式中&#xff0c;?、. 和 * 是三种非常重要的元字符&#xff0c;它们各自有不同的功能和用途&#xff0c;以下是它们的区别&#xff1a; ?&#xff08;问号&#xff09; 功能&#xff1a;表示前面的元素&#xff08;字符、字符集、分组等&#xff09;是可选的&…