Spring AOP功能源码解析

# AOP测试运行

通过@Aspect标记类为切面类,设置好切入点和各种通知类型的方法

# 切面类

@Aspect
@Component
public class MyAspect {
 /**
  * 可复用的切点
  */
 @Pointcut(value = "execution(* org.springframework.felix.service.*.*(..))")
 public void pointCut(){}

 @Before(value = "pointCut()" )
 public void beforeMethod(JoinPoint joinPoint){
  System.out.println("aspect before method");
 }

 @After("pointCut()")
 public void afterMethod(JoinPoint joinPoint){
  System.out.println("aspect after method");
 }

 @Around("pointCut()")
 public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
  System.out.println("aspect around method 1");
  Object proceed = pjp.proceed();
  System.out.println("aspect around method 2");
  return proceed;
 }

 @AfterReturning(value = "pointCut()",returning = "returnObject")
 public void afterReturnMethod(JoinPoint joinPoint,Object returnObject){
  System.out.println("aspect after return method");
 }

 @AfterThrowing(value = "pointCut()" ,throwing = "ex")
 public void afterThrowMethod(JoinPoint joinPoint,Exception ex){
  System.out.println("aspect after throw method");
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

在配置类或者启动类上加上@EnableAspectJAutoProxy注解表示开启了AOP功能,即可运行查看日志

切点表达式的配置以及参数的传递参考Spring文档,中文版本 (opens new window)

# AOP原理

# @EnableAspectJAutoProxy注解的作用

打开该注解的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

 boolean proxyTargetClass() default false;

 boolean exposeProxy() default false;
}

1
2
3
4
5
6
7
8
9
10
11

在该类中发现这样一行代码

@Import(AspectJAutoProxyRegistrar.class)
1

可以发现这个注解的主要作用,就是提示Spring在扫描配置类的时候去导入切面代理注册类 如何导入? (opens new window)

# AspectJAutoProxyRegistrar的作用

spring在解析配置类的时候有一下代码

parser.parse(candidates);
// ...
this.reader.loadBeanDefinitions(configClasses);
1
2
3

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,在解析配置类时被收集,然后在this.reader.loadBeanDefinitions(configClasses)中注册为BeanDefinition 查看AspectJAutoProxyRegistrar#registerBeanDefinitions方法

public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

关键是registerAspectJAnnotationAutoProxyCreatorIfNecessary方法,顾名思义,该方法用来注册AOP代理工具

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {

    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
1
2
3
4
5

可以看到,要注册的类是AnnotationAwareAspectJAutoProxyCreator

所以AspectJAutoProxyRegistrar的作用就是注册AnnotationAwareAspectJAutoProxyCreator的BeanDefinition

# AnnotationAwareAspectJAutoProxyCreator的作用

# AOP组件的创建

追溯该类的继承关系 AOP框架UML

可以发现,该类继承的AbstractAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口,通过后置处理器作用 (opens new window)Bean创建流程 (opens new window)可知其创建时间在Bean组件之前,并且在随后的Bean组件创建过程中对Bean进行干预。

可以猜测AOP创建Bean的代理对象应该是在这一过程中发生。

# 在Bean实例化之前

AbstractAutoProxyCreator#postProcessBeforeInstantiation

判断Bean是否是切面类,切面类是不需要代理的。所以不会有通知方法的通知方法。。。不然还要处理循环通知。。。

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;
  }
  if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return null;
  }
 }
 //...
 return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

isInfrastructureClass方法检查是否继承切面类或有@Aspect注解

重点分析shouldSkip

当前位于AbstractAutoProxyCreator类,shouldSkip会调用之类重写的方法:AspectJAwareAdvisorAutoProxyCreator#shouldSkip

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
 // TODO: Consider optimization by caching the list of the aspect names
 List<Advisor> candidateAdvisors = findCandidateAdvisors();
 for (Advisor advisor : candidateAdvisors) {
  if (advisor instanceof AspectJPointcutAdvisor &&
    ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
   return true;
  }
 }
 return super.shouldSkip(beanClass, beanName);
}
1
2
3
4
5
6
7
8
9
10
11

findCandidateAdvisors 寻找候选的切面通知方法,追踪该方法

调用子类AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors重写的方法

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;
}
1
2
3
4
5
6
7
8
9

继续追踪super.findCandidateAdvisors(),最后调用下面的方法

public List<Advisor> findAdvisorBeans() {
 String[] advisorNames = this.cachedAdvisorBeanNames;
 if (advisorNames == null) {
  advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    this.beanFactory, Advisor.class, true, false);
  this.cachedAdvisorBeanNames = advisorNames;
 }
 if (advisorNames.length == 0) {
  return new ArrayList<>();
 }

 List<Advisor> advisors = new ArrayList<>();
 for (String name : advisorNames) {
  if (isEligibleBean(name)) {
   if (this.beanFactory.isCurrentlyInCreation(name)) {
    if (logger.isTraceEnabled()) {
     logger.trace("Skipping currently created advisor '" + name + "'");
    }
   }
   else {
    try {
     advisors.add(this.beanFactory.getBean(name, Advisor.class));
    }
    //...
   }
  }
 }
 return advisors;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

初始状态下,还没有记录任何切面类,会尝试从容器中获取Advisor类型的Bean,这种是处理通过xml或者代码等非注解方式定义的切面。

回到findCandidateAdvisors方法,查看aspectJAdvisorsBuilder.buildAspectJAdvisors()

遍历所有Bean类型,收集切面通知方法

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<>();
    //此处寻找类型为Object.class 即获取容器中所有的Bean的名称
    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);
     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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

再回到shouldSkip方法,拿到所有的切面通知方法后,判断当前的beanName是不是某个切面的,如果是则需要跳过。

所以在Bean实例化之前,AOP框架做的事情就是收集切面类、切面方法。

# 在Bean初始化之后

AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
 if (bean != null) {
  Object cacheKey = getCacheKey(bean.getClass(), beanName);
  if (this.earlyProxyReferences.remove(cacheKey) != bean) {
   return wrapIfNecessary(bean, beanName, cacheKey);
  }
 }
 return bean;
}
1
2
3
4
5
6
7
8
9

关于早期代理后面再研究,这里先看进行代理包装的方法wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
 //...
 //获取Bean的切面通知
 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
 if (specificInterceptors != DO_NOT_PROXY) {
  //下面会创建代理Bean,先把这个Bean标记成已代理过
  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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

可以发现正是在Bean初始化后的后置处理方法中完成了对Bean的代理。下面探究获取切面通知方法和创建代理对象的细节。

# 获取切面通知方法

深入getAdvicesAndAdvisorsForBean方法,可以看到下面的代码

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
3
4
5
6
7
8
9

findCandidateAdvisors方法会获取所有的通知方法,前面已经分析过。

findAdvisorsThatCanApply顾名思义是过滤出需要执行的通知方法,主要是根据切点指定的表达式进行匹配,只要类(包括父类、接口)方法有一个匹配既算作符合。

extendAdvisors 添加通知方法,主要逻辑如下

public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
 if (!advisors.isEmpty()) {
  boolean foundAspectJAdvice = false;
  for (Advisor advisor : advisors) {
   if (isAspectJAdvice(advisor)) {
    foundAspectJAdvice = true;
    break;
   }
  }
  if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
   advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
   return true;
  }
 }
 return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

主要作用是给找到的通知处理方法数组头部添加一个指定的通知方法,该通知方法的具体作用在下文用到时再作说明。

# 创建代理Bean

选择代理方式,实现了接口的使用JDK动态代理,接口、代理对象、普通类使用CJLIB代理

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  Class<?> targetClass = config.getTargetClass();
  if (targetClass == null) {
   throw new AopConfigException("TargetSource cannot determine target class: " +
     "Either an interface or a target is required for proxy creation.");
  }
  if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
   return new JdkDynamicAopProxy(config);
  }
  return new ObjenesisCglibAopProxy(config);
 }
 else {
  return new JdkDynamicAopProxy(config);
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 代理对象方法执行

根据JDK动态代理和CJLIB代理的原理可以知道,当执行代理对象的方法时,JDK动态代理会首先执行对应的invoke,CJLIB代理会执行intercept方法,

以JDK动态代理为例,CJLIB代理的intercept方法参见CglibAopProxy.DynamicAdvisedInterceptor#intercept


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 {
  //...

  //获取代理方法匹配的通知方法
  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();
  }

  // Massage return value if necessary.
  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;
 }
 //...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 通知方法的二次收集

在创建代理对象的时候所收集的通知方法是该类用到的所有通知方法,具体到被代理对象的某个方法,可能只涉及其中一部分通知方法,所以还需要进一步筛选。为了避免每次调用都筛选一遍,会将筛选的结果缓存起来。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
 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;
}
1
2
3
4
5
6
7
8
9
10

通过被代理方法的切点表达式进行匹配,筛选匹配的通知方法,并封装成拦截器

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
  Advised config, Method method, @Nullable Class<?> targetClass) {

 // This is somewhat tricky... We have to process introductions first,
 // but we need to preserve order in the ultimate list.
 AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
 Advisor[] advisors = config.getAdvisors();
 List<Object> interceptorList = new ArrayList<>(advisors.length);
 Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
 Boolean hasIntroductions = null;

 for (Advisor advisor : advisors) {
  if (advisor instanceof PointcutAdvisor) {
   // Add it conditionally.
   PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
   if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
    boolean match;
    if (mm instanceof IntroductionAwareMethodMatcher) {
     if (hasIntroductions == null) {
      hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
     }
     match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
    }
    else {
     match = mm.matches(method, actualClass);
    }
    if (match) {
     MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
     if (mm.isRuntime()) {
      // Creating a new object instance in the getInterceptors() method
      // isn't a problem as we normally cache created chains.
      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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

上文提到,在第一次收集匹配的通知方法后,会在头部添加一个通知方法ExposeInvocationInterceptor.ADVISOR,

public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {

 public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();

 public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
  @Override
  public String toString() {
   return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
  }
 };
}
1
2
3
4
5
6
7
8
9
10
11

可以发现它的类型是DefaultPointcutAdvisor

public DefaultPointcutAdvisor(Advice advice) {
 this(Pointcut.TRUE, advice);
}
1
2
3

再看Pointcut.TRUE,它是Pointcut的一个实例,它的匹配方法的判断永远返回true,也就是放在头部的这个通知方法会匹配代理类的所有方法。

register.getIntercept方法将通知方法封装成具体通知类型的拦截器方法

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
 List<MethodInterceptor> interceptors = new ArrayList<>(3);
 Advice advice = advisor.getAdvice();
 if (advice instanceof MethodInterceptor) {
  interceptors.add((MethodInterceptor) advice);
 }
 for (AdvisorAdapter adapter : this.adapters) {
  if (adapter.supportsAdvice(advice)) {
   interceptors.add(adapter.getInterceptor(advisor));
  }
 }
 if (interceptors.isEmpty()) {
  throw new UnknownAdviceTypeException(advisor.getAdvice());
 }
 return interceptors.toArray(new MethodInterceptor[0]);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

ExposeInvocationInterceptor

前置通知AspectJMethodBeforeAdvice->MethodBeforeAdviceInterceptor

返回通知 AspectJAfterReturningAdvice->AfterReturningAdviceInterceptor

后置通知 AspectJAfterAdvice

环绕通知 AspectJAroundAdvice

异常通知 AspectJAfterThrowingAdvice

# 通知方法的执行过程

将收集的通知方法封装到方法执行器中,由该对象负责按顺序执行通知方法的invoke,所有通知方法执行完后,执行被代理的目标方法。

public Object proceed() throws Throwable {
 // 通知方法调用完后,执行被代理的目标方法
 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
  return invokeJoinpoint();
 }

 Object interceptorOrInterceptionAdvice =
   this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
  // Evaluate dynamic method matcher here: static part will already have
  // been evaluated and found to match.
  InterceptorAndDynamicMethodMatcher dm =
    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
  Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
  if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
   return dm.interceptor.invoke(this);
  }
  else {
   // Dynamic matching failed.
   // Skip this interceptor and invoke the next in the chain.
   return proceed();
  }
 }
 else {
  // It's an interceptor, so we just invoke it: The pointcut will have
  // been evaluated statically before this object was constructed.
  return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  1. ExposeInvocationInterceptor 调用通知方法的invoke方法,这里先调用ExposeInvocationInterceptor的invoke方法,并将方法执行器传入,以便继续调用后续方法,形成链式调用。
private static final ThreadLocal<MethodInvocation> invocation =
   new NamedThreadLocal<>("Current AOP method invocation");

public Object invoke(MethodInvocation mi) throws Throwable {
 MethodInvocation oldInvocation = invocation.get();
 invocation.set(mi);
 try {
  return mi.proceed();
 }
 finally {
  invocation.set(oldInvocation);
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

可以看到ExposeInvocationInterceptor的作用:将执行器放入ThreadLocal,方便后续通知方法使用。因为spring不确定用户会定义哪些通知方法,为了避免在每个通知方法中都加这一步操作,所以自定义一个首先执行的通知方法。之后调用执行器的proceed方法,将控制权交回执行器。

  1. AspectJAfterThrowingAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
 try {
  return mi.proceed();
 }
 catch (Throwable ex) {
  if (shouldInvokeOnThrowing(ex)) {
   //执行通知方法
   invokeAdviceMethod(getJoinPointMatch(), null, ex);
  }
  throw ex;
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
  1. AfterReturningAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
 //让执行器继续执行
 Object retVal = mi.proceed();
 //上一步执行完已经调用过目标方法,得到了执行结果,在返回执行结果前执行后置通知方法
 this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
 return retVal;
}
1
2
3
4
5
6
7
  1. AspectJAfterAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
 try {
  return mi.proceed();
 }
 finally {
  invokeAdviceMethod(getJoinPointMatch(), null, null);
 }
}
1
2
3
4
5
6
7
8
  1. AspectJAroundAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
 if (!(mi instanceof ProxyMethodInvocation)) {
  throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
 }
 ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
 ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
 JoinPointMatch jpm = getJoinPointMatch(pmi);
 return invokeAdviceMethod(pjp, jpm, null, null);
}
1
2
3
4
5
6
7
8
9
  1. MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
 return mi.proceed();
}
1
2
3
4

时序图如下 (opens new window)

可以看到,被代理的方法的执行时机是由执行器控制,而不是有某种类型的通知来控制,各种通知通过控制mi.proceed()的执行时机来实现前置、后置、环绕等特性。

# 早期引用与早期代理

三级缓存与循环引用 (opens new window)中提到spring通过暴露早期Bean来解决循环引用问题,早期代理正是伴随这个过程产生的。

当发生循环引用,A实例初始化用到B,进入B的创建流程,B实例初始化时用到A,再进入A的创建流程,这时会先从三个缓存中逐一查找,在三级缓存中找到A对应的函数,执行该函数获取A实例

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
 Object exposedObject = bean;
 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
   if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
   }
  }
 }
 return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12

这个过程会执行SmartInstantiationAwareBeanPostProcessor的后置处理方法getEarlyBeanReference

而AOP代理类AbstractAutoProxyCreator是实现了这个方法的

public Object getEarlyBeanReference(Object bean, String beanName) {
 Object cacheKey = getCacheKey(bean.getClass(), beanName);
 this.earlyProxyReferences.put(cacheKey, bean);
 return wrapIfNecessary(bean, beanName, cacheKey);
}
1
2
3
4
5

A对象会被放到早期代理缓存中,然后进入代理包装,如果A对象匹配通知方法的切入点,那么会创建A的代理对象,这样B对象中注入的A对象就是一个代理对象。

之后B对象完成了Bean创建流程,回到A对象的初始化流程,在A对象初始化后会执行 AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
 if (bean != null) {
  Object cacheKey = getCacheKey(bean.getClass(), beanName);
  if (this.earlyProxyReferences.remove(cacheKey) != bean) {
   return wrapIfNecessary(bean, beanName, cacheKey);
  }
 }
 return bean;
}
1
2
3
4
5
6
7
8
9

在这里会再次判断是否生成A的代理对象,由于早期代理对象中已存在,所以不会再次生成代理对象,避免违反单例原则。

上次更新: 2023/04/09, 16:34:32
最近更新
01
go-admin-ui项目仿写练手1-登录页
06-29
02
maven依赖问题
06-17
03
JVM相关命令
02-21
更多文章>