spring aop 分析

一、生成代理对象

spring对象初始化过程(忘记了可以看这里:对象初始化常规流程),属性赋值后对对象做代理增强——这是AOP得以实现的基础

源码入口如下:

Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {
    // 属性赋值方法
    populateBean(beanName, mbd, instanceWrapper);
    // ## 此处做代理增强
    exposedObject = initializeBean(beanName, exposedObject, mbd);
}

我们看下方法实现:

initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 对象初始化前置处理器
    wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    
    // 执行初始方法
    this.invokeInitMethods(beanName, wrappedBean, mbd);
    
    // ## 对象初始化后置处理器
    wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

跟踪后置处理器的执行链路:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // ## 1.获取Advisor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

    // ## 2.创建AOP代理对象
    Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
}

分别观察这两步的实现。

1.获取Advisor

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
// 我们观察“注解实现”
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

List buildAspectJAdvisors() {
    Class beanType = this.beanFactory.getType(beanName);
    // ### A.什么样的对象是Advisor?
    if (this.advisorFactory.isAspect(beanType)) {
        // ### B.Advisor对象如何创建
        List classAdvisors = this.advisorFactory.getAdvisors(factory);
    }
}

从这部分源码又衍生出几个问题。

A.什么样的对象是Advisor

答:被@Aspect对象修饰的对象是Advisor

org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#isAspect
org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#hasAspectAnnotation

private boolean hasAspectAnnotation(Class clazz) {
    // 源码是这么写的
    return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

再思考一下,使用过程中被@Aspect注解修饰的对象是什么?

答案是“一个切面声明”,比如下面的例子。

#### 这是一个切面声明的例子,非spring源码 ####

@Aspect
@Component
public class TransactionAop {
    @Pointcut("execution(* com.jiuxian..service.*.*(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void beginTransaction() {
        System.out.println("before beginTransaction");
    }
    
    @After("pointcut()")
    public void commit() {
        System.out.println("after commit");
    }
}

于是大胆推断——Advisor是不是一个切面对象的封装?

接下来,通过Advisor的创建过程来验证这个推断是否正确。

B.Advisor对象如何创建

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors
List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory){
    // ** 代码1:获取了某种方法 **
    for (Method method : getAdvisorMethods(aspectClass)) {
        // ** 代码2:根据`代码1`的方法构建Advisor **
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
    }
}

代码1:获取的某种方法是什么?

ReflectionUtils.doWithMethods(aspectClass, method -> {
  // 获取非@Poincut注解修饰的所有方法(即@Before、@After注解修饰的方法)
  if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
      methods.add(method);
  }
});

代码2:根据代码1的方法构建的Advisor到底是什么?

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor

Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {
        // == 获取切面信息
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }

        // == 返回Advisor的实现
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

Advisor由InstantiationModelAwarePointcutAdvisorImpl实现,结合代码1来看,Advisor本质是对一个切面方法(@Before、@After等修饰的方法)的封装

之前的推断有些许偏差……

最后我们看一下InstantiationModelAwarePointcutAdvisorImpl是怎么获取Advice的

C.Advisor获取Advice

org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl#getAdvice
org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice

// == 每个注解都对应着一种具体的Advice实现
switch (aspectJAnnotation.getAnnotationType()) {
    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;
}        

2.创建AOP代理对象

前面纵深过大,简单总结一下:
我们用大段篇幅解释了wrapIfNecessary方法的“代码1”部分——这个specificInterceptors数组,其实就是切面中的切面方法(各种@Before、@After注解修饰的方法)的封装。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // ## 1.获取Advisor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

    // ## 2.创建AOP代理对象
    Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
}

接下来,进入“代码2”部分,看看AOP代理是如何创建的!

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
    //== A.先创建AopProxy对象,本质就是new JdkDynamicAopProxy(config)
   return new JdkDynamicAopProxy(config)
                //== B.再调用JdkDynamicAopProxy的getProxy()方法
               .getProxy(classLoader);
}
public Object getProxy(@Nullable ClassLoader classLoader) {
    // ## 第三个参数InvocationHandler传入的是this,所以被代理对象实际执行的是本类的invoke()方法
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

代理执行逻辑,下一章再分析。

二、AOP执行

目前我们已经知道,spring对象初始化后会对声明AOP切面的对象作动态代理

这样在对象方法执行时,会执行相应的代理方法。
而代理对象又包含全部的切面方法封装和切面声明,剩下的只是把它们关联起来。

本章对这部分逻辑加以分析。

// ## 1.构建责任链(全部的advice)
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// ## 2.责任链调度
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, 
            args, targetClass, chain);
retVal = invocation.proceed(); 
 

1.构建责任链

org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice

if (advisor instanceof PointcutAdvisor) {
    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
    if (config.isPreFiltered() 
        || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
        // 获取方法匹配器@Pointcut的expression
        MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
        boolean match;
        // 根据expression表达式匹配目标方法(当前执行的方法)
        match = mm.matches(method, actualClass);

        if (match) {
            // 匹配上了,返回方法的全部拦截器(advice的封装)
            MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }
}

2.责任链调度

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
// 构造函数中赋值chain,方法拦截器 -> advice
protected final List interceptorsAndDynamicMethodMatchers;
// chain的索引
private int currentInterceptorIndex = -1;

--------  ## 以上为属性 ##  --------------

// ### 这是一个递归方法
public Object proceed() throws Throwable {
    // == 1.已经是chain中的最后一个拦截器,则执行原方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return this.invokeJoinpoint();
    } 
    // == 2.否则,执行过滤器方法
    else {
        // 索引自增,获取链中的当前拦截器
        Object interceptorOrInterceptionAdvice 
            = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        
        // ## 拦截器执行(不同的拦截器有不同的实现)
        return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
    }
}

最后观察两种不同的拦截器实现吧。

  • before拦截器

    // == before拦截器(通知)
    org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor#invoke
    {    
      // 先执行拦截器
      this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
      // 再执行方法(递归调用,代码去执行ReflectiveMethodInvocation#proceed)
      return mi.proceed();
    }
  • after拦截器

    // == after拦截器(通知)
    org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
    {
      Object var2;
      try {
          // 先执行方法(递归调用,代码去执行ReflectiveMethodInvocation#proceed)
          var2 = mi.proceed();
      } finally {
          // 再执行拦截器实现
          this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
      }
      return var2;
    }

附录

P6-P7知识合辑

你可能感兴趣的:(spring后端)