【spring源码】 全面简析AOP 注册 代理 执行

1. 简介

AOP说简单点就是通过代理对代码进行一个封装,那要理解AOP就是要解决下面三个问题

  1. 在IOC的创建bean的流程中,在哪里执行了代理操作?
  2. 配置在xml中的< aop:config >, < aop:aspectj-autoproxy/ > 等aop标签是怎么被解析的?
  3. 执行原始方法的过程中,怎么触发@before之类的advice方法。

围绕上述三个问题,我们从注册,代理,执行三方面来看看AOP到底是怎么实现的。

2. 几个概念

spring aop 中有很多概念,有的在代码中是具体实现的,有的没有,所以在这里做一个说明,方便后面的阅读。

  1. advice方法:表示被@before等 注解的方法
  2. advice:在spring中是有具体的advice实现的,用来封装advice方法。每个advice里面都有一个Method对象,就是advice方法。
  3. advisor:封装advice和pointcut一对一的关系。每个advisor里面都包含了一个pointcut和一个advice。
  4. aspect:在spring中只是一个概念,advisor可以理解为它具体的实现。

3. 注册AOP相关BeanDefinition

注册BeanDefinition属于IOC的内容,就不细讲了。这里从获取aop名称空间对应的handler开始说。

3.1 解析入口

aop是自定义的名称空间,所以delegate.parseCustomElement(ele)就是解析的入口。

// DefaultBeanDefinitionDocumentReader
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   if (delegate.isDefaultNamespace(root)) {
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         if (node instanceof Element) {
            Element ele = (Element) node;
            if (delegate.isDefaultNamespace(ele)) {
            	// 解析bean等默认名称空间的标签
               parseDefaultElement(ele, delegate);
            }
            else {
                // ***使用自定义元素解析,入口。***
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
      delegate.parseCustomElement(root);
   }
}
3.2 获得handler

获得aop的handler :AopNamespaceHandler

// BeanDefinitionParserDelegate
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
  // "http://www.springframework.org/schema/aop"
   String namespaceUri = getNamespaceURI(ele);
   if (namespaceUri == null) {
      return null;
   }
    // AopNamespaceHandler
   NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
	//...
   return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
3.3 开始解析

获得对应< aop:config >的parser,开始解析。

// ConfigBeanDefinitionParser
// 对应<aop:config>的parser
public BeanDefinition parse(Element element, ParserContext parserContext) {
   CompositeComponentDefinition compositeDef =
         new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
   parserContext.pushContainingComponent(compositeDef);
   
	// 注册org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator
	// 并把proxy-target-class和expose-proxy属性设置进去
   configureAutoProxyCreator(parserContext, element);

   List<Element> childElts = DomUtils.getChildElements(element);
   for (Element elt: childElts) {
      String localName = parserContext.getDelegate().getLocalName(elt);
      // 解析pointcut
      if (POINTCUT.equals(localName)) {
         parsePointcut(elt, parserContext);
      }
      // 解析advisor
      else if (ADVISOR.equals(localName)) {
         parseAdvisor(elt, parserContext);
      }
      // 解析aspect
      else if (ASPECT.equals(localName)) {
         parseAspect(elt, parserContext);
      }
   }

   parserContext.popAndRegisterContainingComponent();
   return null;
}

主要干两件事情:

  1. 注册一个AspectJAwareAdvisorAutoProxyCreator,这就是用来创建代理的,具体后面说。
  2. 解析xml中的各种aop配置,把它们变成beanDefinition,注册到beanFactory里面。

接下去对parseAspect进行分析,因为parsePointcut和parseAdvisor在parseAspect中都会涉及到。

3.4 parseAspect
// ConfigBeanDefinitionParser
private void parseAspect(Element aspectElement, ParserContext parserContext) {
   String aspectId = aspectElement.getAttribute(ID);
   String aspectName = aspectElement.getAttribute(REF);

   try {
      //...
      NodeList nodeList = aspectElement.getChildNodes();
      boolean adviceFoundAlready = false;
      for (int i = 0; i < nodeList.getLength(); i++) {
         Node node = nodeList.item(i);
          
         // 检查是不是Advice,就是Before,After,Around那五个
         if (isAdviceNode(node, parserContext)) {
            // ...
            // 解析Advice
            AbstractBeanDefinition advisorDefinition = parseAdvice(
                  aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
            beanDefinitions.add(advisorDefinition);
         }
      }

      //...
      // 解析pointcut
      List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
      
      for (Element pointcutElement : pointcuts) {
         parsePointcut(pointcutElement, parserContext);
      }

      // ...
   }
   finally {
      this.parseState.pop();
   }
}

上面的代码主要完成了两件事情:

  1. 解析advice,并把其中的方法method和对应pointcut组合起来,变成一个advisor。
  2. 解析pointcut。

上述两个步骤的目的就是把advisor和pointcut的beanDefinition注册到beanFactory中。接下去就详细说明1和2的具体过程。

3.4.1 parseAdvice
// ConfigBeanDefinitionParser

private AbstractBeanDefinition parseAdvice(
      String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
      List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {

   try {
      this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));

      // 定义一个advice方法的bean。
      // 通过MethodLocatingFactoryBean返回一个类型为Method的bean。
      RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
       // aspect的类名
      methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
       // advice方法名
      methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
       // 表示非用户创建的
      methodDefinition.setSynthetic(true);

       // 创建切面类 的bean
      RootBeanDefinition aspectFactoryDef =
            new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
      aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
      aspectFactoryDef.setSynthetic(true);

       // 创建advice的BeanDefinition
      AbstractBeanDefinition adviceDef = createAdviceDefinition(
            adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
            beanDefinitions, beanReferences);

      // 创建advisor
      RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
      advisorDefinition.setSource(parserContext.extractSource(adviceElement));
      advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
      if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
         advisorDefinition.getPropertyValues().add(
               ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
      }

      // 注册advisor
      parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

      return advisorDefinition;
   }
   finally {
      this.parseState.pop();
   }
}
// ConfigBeanDefinitionParser

private AbstractBeanDefinition createAdviceDefinition(
      Element adviceElement, ParserContext parserContext, String aspectName, int order,
      RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
      List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {

    // 获取对应的Advice类,比如org.springframework.aop.aspectj.AspectJMethodBeforeAdvice
    // 创建RootBeanDefinition
   RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
   adviceDefinition.setSource(parserContext.extractSource(adviceElement));

   adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
   adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
	
    // 加入returningName
   if (adviceElement.hasAttribute(RETURNING)) {
      adviceDefinition.getPropertyValues().add(
            RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
   }
    // 加入throwingName
   if (adviceElement.hasAttribute(THROWING)) {
      adviceDefinition.getPropertyValues().add(
            THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
   }
    // 加入argumentNames
   if (adviceElement.hasAttribute(ARG_NAMES)) {
      adviceDefinition.getPropertyValues().add(
            ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
   }

   ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
    
    // 加入具体的advice方法作为构造函数的第一个参数
   cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
    
	// 加入pointcut作为构造函数的第二个参数
   Object pointcut = parsePointcutProperty(adviceElement, parserContext);
   if (pointcut instanceof BeanDefinition) {
      cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
      beanDefinitions.add((BeanDefinition) pointcut);
   }
   else if (pointcut instanceof String) {
      RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
      cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
      beanReferences.add(pointcutRef);
   }
	// 加入aspect作为第三个参数
   cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);

   return adviceDefinition;
}
3.4.2 parsePointcut
// ConfigBeanDefinitionParser

private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
   String id = pointcutElement.getAttribute(ID);
   String expression = pointcutElement.getAttribute(EXPRESSION);

   AbstractBeanDefinition pointcutDefinition = null;

   try {
      this.parseState.push(new PointcutEntry(id));
       // 创建AspectJExpressionPointcut.class的bd
      pointcutDefinition = createPointcutDefinition(expression);
      pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));

      String pointcutBeanName = id;
      // 注册bd
      if (StringUtils.hasText(pointcutBeanName)) {
         parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
      }
      else {
         pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
      }
		// ...
   }
   finally {
      this.parseState.pop();
   }

   return pointcutDefinition;
}
// ConfigBeanDefinitionParser

protected AbstractBeanDefinition createPointcutDefinition(String expression) {
   RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
   beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
   beanDefinition.setSynthetic(true);
   beanDefinition.getPropertyValues().add(EXPRESSION, expression);
   return beanDefinition;
}
总结

解析< aop:config >总体流程:

  1. 找到AopNamespaceHandler,找到里面的ConfigBeanDefinitionParser

  2. ConfigBeanDefinitionParser主要干两件事情:1. 注册AutoProxyCreator,2. 解析aspect

  3. aspect解析过程如下:(bd=beanDefinition)

    3.1 解析advice,这个过程中需要用到advice方法所在类的工厂bd,advice方法的工厂bd,对应Pointcut的bd。最终生成一个AspectJPointcutAdvisor,只注册这个AspectJPointcutAdvisor的bd。

    3.2 解析并注册pointcut的bd。pointcut是原型的,非singleton。

4. 代理

在注册BeanDefinition过程中提到了AspectJAwareAdvisorAutoProxyCreator,这个类就是实现代理的核心,它实际上是一个BeanPostProcessor。所以代理的时机就是bean初始化完成之后

4.1 代理开始postProcessAfterInitialization
// AbstractAutoProxyCreator
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;
}

// AbstractAutoProxyCreator
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   // 是否是基础类(Advice,Pointcut等类)或者需要跳过
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

    // 获得当前bean需要的advice或者Advisor
   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;
}

从上面的代码可以看出代理就是两个步骤:

  1. 获取所有合适的advisor。
  2. 创建proxy对象。

接下去从这两方面进行详细分析。

4.2 获取所有合适的advisor
// AbstractAdvisorAutoProxyCreator

protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
   // 找到合适的Advisors
   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
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 在所有Advisor中挑可用于当前bean的,需要符合下面的要求
    // 1. IntroductionAdvisor按类匹配
    // 2. PointcutAdvisor按方法匹配,bean中的方法至少有一个满足advisor的要求
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, 
                                                             beanClass, beanName);
    // 在eligibleAdvisors的第0个位置加一个ExposeInvocationInterceptor,把MethodInvocation放到一个自己的threadlocal里面,getjoinPoint的时候会用到
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

找所有的advisor

// AbstractAdvisorAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
   Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
   // 根据Advisor类,找到所有的bean
   return this.advisorRetrievalHelper.findAdvisorBeans();
}
4.3 创建代理
// 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);
   }
	// 创建proxyFactory
   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);
	// 根据proxy-target-class,当前bean有没有实现接口等决定要不要用cglib代理。
   if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }
	// specificInterceptors里面可能有advice,把它变成advisor
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   // 把advisors写进proxyFactory,后续proxyFactory会被传入AopProxy 
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }
	// 获取代理
   return proxyFactory.getProxy(getProxyClassLoader());
}
// ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {
   return createAopProxy().getProxy(classLoader);
}

// ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	return getAopProxyFactory().createAopProxy(this);
}

//DefaultAopProxyFactory
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);
      }
       // 用cglib,这个config是一个proxyFactory,里面存了匹配的advisors
      return new ObjenesisCglibAopProxy(config);
   }
   else {
       // 用jdk
      return new JdkDynamicAopProxy(config);
   }
}
总结

代理过程主要分成两部分:

  1. 获得所有当前bean可用的advisor
    1.1 按类型找到所有的advisor。
    1.2 用advisor中的pointcut决定当前bean需要用到哪些advisor。具体规则在代码的注释中。
  2. 创建proxy
    2.1 创建proxyFacotory,写入上一步找到的advisors
    2.2 决定用cglib还是jdk的proxy: proxy-target-class为true强制用CGLIB,否则默认用JDK PROXY,如果没有接口,用CGLIB。
    2.3 用proxyFacotory创建ObjenesisCglibAopProxy或者JdkDynamicAopProxy,会把proxyFacotory作为参数传入,这样AopProxy就能得到advisors了。
    2.4 从JdkDynamicAopProxy或者ObjenesisCglibAopProxy中获得proxy,这些就主要是代理的知识了。

5. 执行

只分析用JdkDynamicAopProxy进行代理的情况。

5.1 入口:invoke

重点就是invocation.proceed()。

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

      Object retVal;
		// 暴露Proxy,实现类内调用时使用代理
		// 如果不设置exposeProxy,类内一个方法调用另一个方法是执行原生方法的
      if (this.advised.exposeProxy) {
         // Make invocation available if necessary.
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }

      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);

      // 获得匹配当前方法的Interceptor链,如果advisor实现了MethodInterceptor,
      // 直接返回,否则取出其中的advice,包装成MethodInterceptor,返回。
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      
      if (chain.isEmpty()) {
   		// 执行原始方法
         Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
         retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
      }
      else {
         // 根据interceptor链创建MethodInvocation
         MethodInvocation invocation =
               new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
         // ***重点:开始执行interceptor链***
         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())) {
         // 返回this
         retVal = proxy;
      }
     // ...
      }
      return retVal;
   }
   finally {
      // ...
}

上面的代码主要干三件事情:

  1. 如果需要的话,暴露当前的proxy
  2. 获取当前方法需要的所有advisor并转换成interceptor,组成一个interceptor链chain。
  3. 根据chain,创建MethodInvocation ,通过invocation.proceed执行interceptor链。

接下去详细分析invocation.proceed。

5.2 proceed

这个地方会比较绕,先明确一点,这个方法的调用者是invocation,一个MethodInvocation的对象。

// ReflectiveMethodInvocation
private int currentInterceptorIndex = -1;

public Object proceed() throws Throwable {
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
     // 说明所有的interceptor都执行完了,接下去可以执行原始的方法了。
      return invokeJoinpoint();
   }
	// 先++currentInterceptorIndex,然后获取即将要执行的interceptor
   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 {
      // 执行interceptor,注意传入的参数this!
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

重点就是最后一行代码,主要传入的参数:this,这个很重要。
以一个使用了@before和@after的bean为例子,具体分析一下。
此时需要执行的interceptor chain里面包含三个interceptor:

  1. ExposeInvocationInterceptor
  2. MethodBeforeAdviceInterceptor
  3. AspectJAfterAdvice

先执行ExposeInvocationInterceptor

// ExposeInvocationInterceptor
private static final ThreadLocal<MethodInvocation> invocation =
			new NamedThreadLocal<>("Current AOP method invocation");

public Object invoke(MethodInvocation mi) throws Throwable {
   MethodInvocation oldInvocation = invocation.get();
    // 暴露当前的MethodInvocation
   invocation.set(mi);
   try {
      return mi.proceed();
   }
   finally {
      invocation.set(oldInvocation);
   }
}

此时传入了一个MethodInvocation,这个就是调用5.2 proceed方法的MethodInvocation。重点就是return mi.proceed(),这个方法不就又跳回到5.2了吗?

Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

这时候currentInterceptorIndex就会+1,就得到了下一个interceptor:MethodBeforeAdviceInterceptor

执行MethodBeforeAdviceInterceptor

// MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
    // 调用@before方法
   this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    // 这一步调用其实又回到了ReflectiveMethodInvocation的proceed,就是上面的那个函数。
   return mi.proceed();
}

同理,最后return mi.proceed();又会回到5.2的proceed

Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

此时得到的就是AspectJAfterAdvice。

执行AspectJAfterAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
   try {
      return mi.proceed();
   }
   finally {
      invokeAdviceMethod(getJoinPointMatch(), null, null);
   }
}

它会先执行proceed,然后再执行after的代码。

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
     // 说明所有的interceptor都执行完了,接下去可以执行原始的方法了。
      return invokeJoinpoint();
   }

现在就是if中的情况了,所有的interceptor都执行完毕,可以执行原始的方法了。

总结

执行方法过程如下:
首先调用JdkDynamicAopProxy中的invoke方法

  1. 如果需要的话,暴露当前的proxy
  2. 获取当前方法需要的所有advisor并转换成interceptor,组成一个interceptor链chain。
  3. 根据chain,创建MethodInvocation ,通过invocation.proceed执行interceptor链。

然后调用MethodInvocation的proceed,它会按顺序调用interceptor,interceptor内部又会调用MethodInvocation的proceed,就是一个递归的过程。

6. aop:aspectj-autoproxy 注解方式

注解方法跟上述过程其实差不多,也是这三部分,主要区别是以下两点:

  1. 注册过程中不需要去解析advisor了,用到的parser是AspectJAutoProxyBeanDefinitionParser。注册进去的AutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator。
public BeanDefinition parse(Element element, ParserContext parserContext) {
    // 就是注册了一个AnnotationAwareAspectJAutoProxyCreator
   AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
   extendBeanDefinition(element, parserContext);
   return null;
}
  1. 那么问题来了,advisor的定义是在哪里注册进去的呢?
    4.2中有一步是获取所有的advisor,在AnnotationAwareAspectJAutoProxyCreator中,它的实现如下。
// AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
   
    // 调用父类的方法,也就是上面的那个方法。
    // 从所有的beanDefinition中找Advisor类的,然后得到对应的bean。
   List<Advisor> advisors = super.findCandidateAdvisors();
    
    // 找到所有带@Aspect注解的类,然后根据@before等五个advice方法去生成Advisor,中间会解析pointcut
   if (this.aspectJAdvisorsBuilder != null) {
      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   }
   return advisors;
}

先调用父类的方法,然后再根据注解去解析,然后直接创建对应的advice,pointcut,advisor就好了。

7.怎样会调用postProcessBeforeInstantiation进行代理

不知道什么场景下会用到。只从代码上分析可以调用的情况。
下面的getCustomTargetSource是关键

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;
		}
	}

	// Create proxy here if we have a custom TargetSource.
	// Suppresses unnecessary default instantiation of the target bean:
	// The TargetSource will handle target instances in a custom fashion.
	// ******关键代码*****
	TargetSource 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;
}
// 默认是空的
// AbstractAutoProxyCreator
private TargetSourceCreator[] customTargetSourceCreators;

protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
	// We can't create fancy target sources for directly registered singletons.
	if (this.customTargetSourceCreators != null &&
			this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
		// 遍历customTargetSourceCreators找一个可以产生TargetSource的
		for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
			TargetSource ts = tsc.getTargetSource(beanClass, beanName);
			if (ts != null) {
				// Found a matching TargetSource.
				if (logger.isTraceEnabled()) {
					logger.trace("TargetSourceCreator [" + tsc +
							"] found custom TargetSource for bean with name '" + beanName + "'");
				}
				return ts;
			}
		}
	}

	// No custom TargetSource found.
	return null;
}

需要往TargetSourceCreator数组里面传一些自己定义的TargetSourceCreator,然后在解析beanDefinition的时候不要用默认的ProxyCreator,自己在xml文件中配一个,名字如下。

// AopConfigUtils
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

这样在解析<aop:config>的时候就会用我们自己的定义的ProxyCreator,而不是去建一个默认的beanDefinition

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值