关于spring:spring-aop-分析

39次阅读

共计 8861 个字符,预计需要花费 23 分钟才能阅读完成。

一、生成代理对象

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<Advisor> buildAspectJAdvisors() {Class<?> beanType = this.beanFactory.getType(beanName);
    // ### A. 什么样的对象是 Advisor?if (this.advisorFactory.isAspect(beanType)) {
        // ### B.Advisor 对象如何创立
        List<Advisor> 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<Advisor> 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<Object> 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 常识合辑

正文完
 0