由于md文档部分hugo插件语法不兼容,建议访问作者网站查阅文章:wlizhi.cc
spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework 。
链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。
1 主流程
AOP是通过 BeanPostProcessor.postProcessAfterInitialization() 实现的,来到 doCreateBean() -> initializeBean(),在初始化方法执行完成后,会调用 applyBeanPostProcessorsAfterInitialization(),这里循环调用了所有 BeanPostProcessor 的 postProcessAfterInitialization(),AOP 的入口就在其中的一个实现类,也是 AbstractAutoProxyCreator 的子类实现。
在生成代理之前,spring 会根据扫描规则,搜集容器中注册的所有 Advisor 实例、并搜集通知方法(@Aspect 注解的类中的@Before、@Around等注解标识的方法),将其封装成 Advisor。然后逐个与当前 bean 实例匹配,匹配到的放入一个集合中。
来到入口方法 postProcessAfterInitialization(),源码如下:
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 如果是FactoryBean,cacheKey是 &+beanName拼接而成,如果benaName为空,则是类名称。
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// TODO 必要时包装给定的bean,即是否有资格被代理。
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
}
如果需要生成代理(自定义切面、事务等),会调用 wrapIfNecessary()。
wrapIfNecessary() 是这么定义的:
{{< highlight java “linenos=table,hl_lines=7 11 12,linenostart=1” >}}
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 省略无关代码…
// TODO 重点:如果有需要增强,就创建代理对象,这里会循环此类中所有的方法,如果有增强匹配到类中的方法,就会将增强对象封装到list中。
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// TODO 重点:创建代理对象
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;
}
}
{{< /highlight >}}
{{< admonition title=“注意” open=true >}}
从源码中可以看到,关键点有两个:
- 搜集容器中所有匹配当前bean的通知方法。(如果当前bean中有方法被 pointCut 匹配到,就满足条件,将对应的通知方法封装到数组中返回)
- 根据匹配的通知方法列表,创建代理对象。(这里会将已排序的通知方法列表,生成一个执行链,缓存起来,当代理对象方法被调用时调用回调方法的时候,会火炬传递式的调用执行链中的通知方法。JDK动态代理和cgliib封装方式大同小异,通知方法都在回调函数所在的类中作为一个成员缓存。)
{{< /admonition >}}
2 搜集封装Advisor
2.1 搜集流程
getAdvicesAndAdvisorsForBean() 会调用到 findEligibleAdvisors()。来到这个方法:
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//查找到所有的增强方法,封装成Advisor对象。这里查找了两种增强,一种是实现了Advisor的实例,一种是带有@Aspect注解的bean实例中定义的增强方法。
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 根据每个增强中的切点表达式,进行匹配,筛选出合适的增强实例列表。
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
// 对增强方法进行排序,可以不看。
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
}
这里分为了两步:
- 收集到容器中所有的增强方法、封装成 Advisor(如果本身就是 Advisor,直接返回)。
- 从这所有的 Advisor 中筛选出匹配当前 bean 的 Advisor 列表。
从 AbstractAutoProxyCreator的注册 已经知道,这里使用的是 AnnotationAwareAspectJAutoProxyCreator。
进入 findCandidateAdvisors():
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
@Override
protected List<Advisor> findCandidateAdvisors() {
// TODO 从父类中获取,这里获取了所有注入到容器中的Advisor类型的实例。事务的增强实例,就是在这里查找的。
// 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) {
// TODO 将beanFactory中缓存的所有bean实例,依次校验是否带有@Aspect注解,如果有,将其中的
// 增强方法、切点表达式等信息,封装成Advisor。advisors变量最终存储了所有切面的增强方法封装。
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
}
看上面代码,首先,从父类中查找 Advisor列表,然后调用 buildAspectJAdvisors(),将两者结果聚合到一个列表。
先看父类中的代码:
public class BeanFactoryAdvisorRetrievalHelper {
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// 从容器中获取所有的Advisor类型的额bean名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
// 省略非关键代码...
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
// 从beanFactory中获取所有的Advisor类型的实例,事务支持TransactionAttributeSourceAdvisor实际上就是一个Advisor。
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
return advisors;
}
}
这里搜集了容器中所有 Advisor 类型的 beanName,并将其缓存。然后调用 getBean(),将其实例化。(事务的 Advisor 其实就是在这里创建的
)
再看子类中的代码 buildAspectJAdvisors():
public class 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) {
// 如果不是合格的beanName,则跳过
if (!isEligibleBean(beanName)) {
continue;
}
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 判断当前beanType是否是一个切面。判断类上是否有@Aspect
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
// 创建切面元数据实例,里面封装了切面类型,切点表达式等信息。
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// 默认就是SINGLETON
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// TODO 获取Advisor,这里封装了当前Aspect类中的增强方法,每个增强方法都会封装成一个Advisor。
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 将Advisor放入到缓存中,从上面的流程获取时,会先走缓存,缓存中有,就不会遍历查找了。
// 这个代码块使用了双检索,这块代码在spring容器启动时,只会执行一次。
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
// 省略...
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
// 省略...
// 根据切面名称,从缓存中获取到指定的增强实例,封装起来返回。
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;
}
}
上面代码略长、主要看带有注释的地方。代码主要流程:
- 获取到容器中所有的 beanName,遍历。
- 挨个判断,如果当前类上有 @Aspect,则解析这个类中通知方法及切入点表达式等信息。
- 调用 getAdvisors() 获取类中所有的通知方法,将其封装成 Advisor,作为一个列表返回。
- 放入缓存,下次进入就不会再遍历所有 beanNames 计算,而是从缓存中获取。
重点就在 getAdvisors(),在此之前,先来看看 isAspect():
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
public boolean isAspect(Class<?> clazz) {
// 这里判断类型是否包含@Aspect
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
}
isAspect() 中的逻辑非常简单,判断当前类中是否有 @Aspect 注解(第二个条件可以忽略,判断类中是否有字段以 ajc$
一个特殊的标识开头的)。
来到 getAdvisors():
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取切面类型,切面名称
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 获取增强方法,并按照方法名称排序。
for (Method method : getAdvisorMethods(aspectClass)) {
// TODO 将增强方法封装成Advisor,并添加到advisors变量中,最终会将这个变量返回。
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 引介,基本用不到,这里代码省略...
return advisors;
}
}
注意:这个方法是在一个循环中调入进来的,aspectInstanceFactory 中封装了当前遍历到的 beanName 以及 beanFactory 的信息。
- getAdvisorMethods(),获取到所有非切点表达式的方法,也就是不带 @PointCut 注解的方法。
- 遍历这些方法,getAdvisor() 将方法封装成 Advisor。
getAdvisorMethods() 源码如下:
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
// 先按照注解排序、如果是相同的注解,就按照方法名称排序。
methods.sort(METHOD_COMPARATOR);
return methods;
}
}
排序的代码有一点绕,嵌套的 lambda 表达式,是这么定义的(可以不看,实际业务中一般一个切面类只定义一个通知方法):
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
private static final Comparator<Method> METHOD_COMPARATOR;
static {
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> annotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (annotation != null ? annotation.getAnnotation() : null);
});
// 先按照注解排序、如果是相同的注解,就按照方法名称排序。
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
}
}
先使用 methodNameComparator 进行排序,如果排序结果相等,再使用 methodNameComparator 进行排序。每个比较器排序前都会使用 Converter<S, T>
转换其类型。
调用 getAdvisor():
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 将当前方法、类型作为参数。获取PointCut对象,最重要的是从注解中获取表达式
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 这里封装了切点表达式、切面类型、增强方法等信息。它是Advisor的一个实现类,最终会加入到代理实例的执行链中。
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
}
- 获取到通知方法的 PointCut() 对象,如果有方法没有切点表达式,直接返回null,这种情况会被忽略,不被加入到 Advisor 列表中。
- 创建 Advisor 对象,封装切点表达式、通知方法等必要信息。
2.2 PointCut的获取
关于如何获取 PointCut 的,源码如下:
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 找到切面相关注解,并把注解信息解析出来,包装成AspectJAnnotation
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 将切点表达式封装到AspectJExpressionPointcut中。这里封装了切点表达式、切面类型等信息。
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
}
接着看 findAspectJAnnotationOnMethod():
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
/** 这里定义了切面中支持的注解,前置、后置、环绕等通知类型 */
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
// 步骤一
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
// 循环去找注解,并把注解信息解析出来,包装成AspectJAnnotation
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
// 步骤二
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
// 找的规则就是找注解的父注解,递归的方式去找,直到找到目标注解为止
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
// 把注解里面对的信息解析出来,然后包装成AspectJAnnotation对象
return new AspectJAnnotation<>(result);
}
else {
return null;
}
}
}
从上面代码可以看到,ASPECTJ_ANNOTATION_CLASSES数组常量中,预定义了支持切点表达式的注解。如果能在当前方法上找到任何一种,就将这个切点信息封装成 AspectJAnnotation。
2.3 Advisor的初始化
这里还有一个重点,new InstantiationModelAwarePointcutAdvisorImpl 中的初始化过程。
构造函数源码如下:
{{< highlight java “linenos=table,hl_lines=18,linenostart=1” >}}
final class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 切点、切面名称、通知方法名称、等等一系列信息的封装
this.declaredPointcut = declaredPointcut;
// 省略…
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// 省略...
}else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// TODO 重点,实例化的过程,这里封装了具体的Advice
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
}
{{< /highlight >}}
重点方法是 instantiateAdvice(),这里完成了 Advice 的创建。
继续向下跟踪代码:
final class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
// TODO 重点getAdvice
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
}
来到 getAdvice():
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 获取切面类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 查找切点表达式、五种通知增强注解。@Before等五种。
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 省略部分代码...
AbstractAspectJAdvice springAdvice;
// TODO 执行判断,针对不同类型的通知,封装不同类型的Advice
// 这几个Advice的实现类要记一下。主要以是否实现MethodInterceptor来区分,有的实现了,有的没有。
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();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// 省略...
return springAdvice;
}
}
{{< admonition tip= title=“注意” open=true >}}
上面代码中,AspectJMethodBeforeAdvice 等几个Advice的实现要看一下,这里五个 Advice 实现,部分实现了MethodInterceptor。
实现了MethodInterceptor的:
- AspectJAroundAdvice
- AspectJAfterAdvice
- AspectJAfterThrowingAdvice
未实现MethodInterceptor的 --> 生成执行链时依赖的适配器:
- AspectJMethodBeforeAdvice --> MethodBeforeAdviceAdapter
- AspectJAfterReturningAdvice --> AfterReturningAdviceAdapter
另外还有一个未用到的Advice,也没有实现MethodInterceptor
ThrowsAdvice --> ThrowsAdviceAdapter
在生成搭理对象后,真正执行代理方法生成执行链的时候,实现了MethodInterceptor和未实现前者的,调用逻辑上有些差别。
实现了MethodInterceptor的,会直接加入到执行链,未实现的,会通过对应的适配器,调用 getInterceptor() 来获取 MethodInterceptor,然后将 MethodInterceptor 加入执行链。(这些是后话)
{{< /admonition >}}
3 筛选出匹配的Advisor
在获取到容器中所有的通知方法封装成的 Advisor 后,会调用 findAdvisorsThatCanApply(),将 beanName 放入到一个 ThreadLocal 类型的变量中,然后调用 findAdvisorsThatCanApply() 的重载方法。调用完毕之后,会将 ThreadLocal 变量中的 beanName置空。
findAdvisorsThatCanApply() 重载方法源码如下:
public abstract class AopUtils {
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 先处理IntroductionAdvisor类型的增强
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 再处理其他类型的增强
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 我们自定义的切面,就会走到这里,使用已经封装的PointcutAdvisor,根据切点表达式进行匹配,具体的匹配过程,不用看。
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
}
调用 canApply(),这里进行了切点表达式与方法的匹配,如果匹配成功,将 Advisor 放入到集合中,否则就跳过。
当将所有的 Advisor 遍历完毕,最终匹配成功的 Advisor 会被筛选出来,放入到一个新的集合中,最终生成的执行链中的通知方法,就来自筛选后的 Advisor 集合(这个集合在创建代理前还有一次新增操作)。
看 canApply(),这里进行了匹配:
public abstract class AopUtils {
// 步骤一
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//切点表达式匹配。
return 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) {
// 省略...
// 这里做了切入点表达式的匹配,匹配通过的返回true,具体的匹配过程不用看,不是重点。
for (Class<?> clazz : classes) {
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;
}
}
从上面代码可以看到,PointcutAdvisor 类型的,最终会遍历类中所有的方法,根据切点表达式,进行一一匹配,如果匹配成功,返回true,否则返回false。
4 搜集容器中所有的Advisor的流程
- 父类调用流程:
{{< mermaid >}}
graph LR;
B(findCandidateAdvisors) -->|One| C(super.findCandidateAdvisors)
C --> CA{findAdvisorBeans}
CA -->|One| CAA(beanNamesForTypeIncludingAncestors)
CA -->|Two| CAB(beanFactory.getBean)
{{< /mermaid >}} - 子类调用流程:
{{< mermaid >}}
graph TB;
B(findCandidateAdvisors) -->|Two| D(buildAspectJAdvisors)
D -->|ForEach| E(beanNames)
E --> F(isAspect) -->|true| G{getAdvisors}
G -->|One| GA(getAdvisorMethods)
GA --> GAA1(doWithMethods) --> GAA2(“getAnnotation(method, Pointcut.class)”)
G -->|Two| GB(getAdvisor)
GB --> GBA(getPointcut)
GBA --> GBAA(findAspectJAnnotationOnMethod) -->|forEach| GBAA1(ASPECTJ_ANNOTATION_CLASSES)
GBAA1 --> GBAA2(findAnnotation) --> GBAA3(“new AspectJAnnotation<>(result)”)
{{< /mermaid >}}