【Spring源码】一个我们日常使用的AOP实现

前言

关于 AOP 在日常开发中应该不算是一个新的名词了,AOP 可以帮助我们把业务之外,但是很多方法都需要调用的方法,无感的方外外部,并且通过配置让外部的 AOP 函数自动织入目标方法中。

常见的业务有:

  1. 记录方法调用的信息,时长;
  2. 初始化当前用户信息上下文,方便在业务内部快速获取。

那我就改改我之前的 Context 用的例子,来康康 Spring 是怎么做的。

准备

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <bean class="cn.liweidan.confbean.MyBeanConfiguration"/>
    <context:annotation-config/>
    <!-- 开启自动代理支持 -->
    <aop:aspectj-autoproxy/>

</beans>

MyBeanConfiguration.java

@Configurable
public class MyBeanConfiguration {

//  @Bean
//  public MyBean myBean() {
//    MyBean myBean = new MyBean();
//    myBean.setName("Weidan");
//    return myBean;
//  }

  @Bean
  public NoInterfaceService noInterfaceService() {
    return new NoInterfaceService();
  }

  @Bean
  public MethodAop methodAop() {
    return new MethodAop();
  }

  @Bean
  public HasInterfaceService hasInterfaceService() {
    return new HasInterfaceServiceImpl();
  }

}

一个没有接口实现的业务层:

public class NoInterfaceService {

  public void test() {
    System.out.println("这是方法里面的内容");
  }

}

一个有接口实现的业务层:

public interface HasInterfaceService {

  void testHasInterface();

}

public class HasInterfaceServiceImpl implements HasInterfaceService {

  @Override
  public void testHasInterface() {
    System.out.println("一个有接口的方法的内部");
  }

}

一个注解方式的自动织入 Bean

@Aspect
public class MethodAop {

    @Pointcut("execution(* cn.liweidan.confbean.service.*.*(..)) || execution(* cn.liweidan.confbean.services.impl.*.*(..))")
    public void aopPoint() {}

    @Around("aopPoint()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println(joinPoint.getSignature().getDeclaringTypeName() + "方法开始执行");
        Object proceed = joinPoint.proceed();
        System.out.println(joinPoint.getSignature().getDeclaringTypeName() + "方法完成执行");
        return proceed;
    }

}

测试用例:

public class ConfigBeanTest {

  @Test
  public void testAop() {
    BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml");
    NoInterfaceService bean = bf.getBean(NoInterfaceService.class);
    bean.test();
    HasInterfaceService hasInterfaceService = bf.getBean(HasInterfaceService.class);
    hasInterfaceService.testHasInterface();
  }

}

试运行一下:

cn.liweidan.confbean.service.NoInterfaceService方法开始执行
这是方法里面的内容
cn.liweidan.confbean.service.NoInterfaceService方法完成执行
cn.liweidan.confbean.services.HasInterfaceService方法开始执行
一个有接口的方法的内部
cn.liweidan.confbean.services.HasInterfaceService方法完成执行

好了成功!

注册标签处理器

之前几篇我都直接跳过 xml 解析,这次终于跳不过去了。因为在处理器这一块,Spring 确实能够让我特别惊喜,模块间的解耦仿佛就是我不知道你有什么东西我也不关心但是最后我就能够调用到你的傲娇姑娘的任性。

让我们回到第一篇的 BeanDefinitionDocumentReader读取配置文档 这一节中(传送门),我重新贴一下代码:

@SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
 // Any nested <beans> elements will cause recursion in this method. In
 // order to propagate and preserve <beans> default-* attributes correctly,
 // keep track of the current (parent) delegate, which may be null. Create
 // the new (child) delegate with a reference to the parent for fallback purposes,
 // then ultimately reset this.delegate back to its original (parent) reference.
 // this behavior emulates a stack of delegates without actually necessitating one.
 BeanDefinitionParserDelegate parent = this.delegate;
 this.delegate = createDelegate(getReaderContext(), root, parent);

 if (this.delegate.isDefaultNamespace(root)) {
  String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
  if (StringUtils.hasText(profileSpec)) {
   String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
     profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
   // We cannot use Profiles.of(...) since profile expressions are not supported
   // in XML config. See SPR-12458 for details.
   if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
    if (logger.isDebugEnabled()) {
     logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
       "] not matching: " + getReaderContext().getResource());
    }
    return;
   }
  }
 }

 preProcessXml(root);
 // 来到这句话中,因为这句话会解析到配置文件中的 <aop:aspectj-autoproxy/> 元素中。
 parseBeanDefinitions(root, this.delegate);
 postProcessXml(root);

 this.delegate = parent;
}

// 在这个方法中实现解析:
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)) {
          parseDefaultElement(ele, delegate);
        }
        else {
          // 因为 <aop:aspectj-autoproxy/> 并不是默认的命名空间(默认只有:http://www.springframework.org/schema/beans),
          // 所以需要调用自定义的处理器来解析元素.
          delegate.parseCustomElement(ele);
        }
      }
    }
  }
  else {
    delegate.parseCustomElement(root);
  }
}

/**
     * Parse a custom element (outside of the default namespace).
     * @param ele the element to parse
     * @return the resulting bean definition
     */
@Nullable
public BeanDefinition parseCustomElement(Element ele) {
  return parseCustomElement(ele, null);
}

/**
     * Parse a custom element (outside of the default namespace).
     * @param ele the element to parse
     * @param containingBd the containing bean definition (if any)
     * @return the resulting bean definition
     */
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
  // AOP的命名空间是http://www.springframework.org/schema/aop
  String namespaceUri = getNamespaceURI(ele);
  if (namespaceUri == null) {
    return null;
  }
  // 开始从上下文中寻找合适的解析器,第一个方法只是简单地返回一个实例
  // 那下面直接看看 resolve 怎么处理的
  NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
  if (handler == null) {
    error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
    return null;
  }
  return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

在寻找解析器这一步就挺骚了,直接从所有模块中的 META-INF/spring.handlers 中开始查找其他模块配置的解析器:

    @Override
    @Nullable
    public NamespaceHandler resolve(String namespaceUri) {
    // 获取所有的解析器,依赖的所有 jar 包都会读取
        Map<String, Object> handlerMappings = getHandlerMappings();
        // 因为获取的是字符串,所以需要通过反射实例化解析器对象
    Object handlerOrClassName = handlerMappings.get(namespaceUri);
        if (handlerOrClassName == null) {
            return null;
        }
        else if (handlerOrClassName instanceof NamespaceHandler) {
            return (NamespaceHandler) handlerOrClassName;
        }
        else {
            String className = (String) handlerOrClassName;
            try {
                Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
                if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                    throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                            "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
                }
        // 实例化对象
                NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
                namespaceHandler.init();
        // 覆盖之前的字符串,以便后面如果还需要可以直接返回对象。
                handlerMappings.put(namespaceUri, namespaceHandler);
                return namespaceHandler;
            }
            catch (ClassNotFoundException ex) {
                throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
                        "] for namespace [" + namespaceUri + "]", ex);
            }
            catch (LinkageError err) {
                throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
                        className + "] for namespace [" + namespaceUri + "]", err);
            }
        }
    }

    /**
     * 惰性读取所有解析器.
     */
    private Map<String, Object> getHandlerMappings() {
        Map<String, Object> handlerMappings = this.handlerMappings;
        if (handlerMappings == null) {
            synchronized (this) {
                handlerMappings = this.handlerMappings;
                if (handlerMappings == null) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
                    }
                    try {
            // 这一步就是从配置的 handlerMappingsLocation=DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers" 中去查找其他模块编写的配置文件,然后获取到对象的自定义标签的解析器
                        Properties mappings =
                                PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
                        if (logger.isTraceEnabled()) {
                            logger.trace("Loaded NamespaceHandler mappings: " + mappings);
                        }
            // 开始加载解析器,然后缓存起来返回到上面的方法中。
                        handlerMappings = new ConcurrentHashMap<>(mappings.size());
                        CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
                        this.handlerMappings = handlerMappings;
                    }
                    catch (IOException ex) {
                        throw new IllegalStateException(
                                "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
                    }
                }
            }
        }
        return handlerMappings;
    }

AOP模块中的 META-INF/spring.handlers

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

然后就可以开始使用其他模块的处理器开始处理元素了:

@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
  // AOP的命名空间是http://www.springframework.org/schema/aop
  String namespaceUri = getNamespaceURI(ele);
  if (namespaceUri == null) {
    return null;
  }
  // 开始从上下文中寻找合适的解析器,第一个方法只是简单地返回一个实例
  // 那下面直接看看 resolve 怎么处理的
  NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
  if (handler == null) {
    error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
    return null;
  }
  // 开始处理
  return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

初始化AOP所需环境

// NamespaceHandler内的方法:
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
 BeanDefinitionParser parser = findParserForElement(element, parserContext);
 return (parser != null ? parser.parse(element, parserContext) : null);
}
// 还有一个抽象的方法
@Nullable
BeanDefinition parse(Element element, ParserContext parserContext);

//AopNamespaceHandler处理器的实现:
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
  AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
  extendBeanDefinition(element, parserContext);
  return null;
}

首先看看 AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); 这句话,看方法名初步判断是注册一个 BeanDefinition 以便后续用来解析基于 Java注解AOP Advisor

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  ParserContext parserContext, Element sourceElement) {

 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
   parserContext.getRegistry(), parserContext.extractSource(sourceElement));
 // 因为只是简单配置标签,没有定义属性,所以这个方法里面是个空的执行
 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
 // 将第一句话拿到的 beanDefinition 注册到 bf 中去,使用 Component 组的形式进行注册。
 registerComponentIfNecessary(beanDefinition, parserContext);
}
// 调用了这里:
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  BeanDefinitionRegistry registry, @Nullable Object source) {

  return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
// 然后再继续调用了这里:
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
  Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

  Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

  if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
    BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
    if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
      int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
      int requiredPriority = findPriorityForClass(cls);
      if (currentPriority < requiredPriority) {
        apcDefinition.setBeanClassName(cls.getName());
      }
    }
    return null;
  }

  RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
  beanDefinition.setSource(source);
  beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
  beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
  return beanDefinition;
}

果然就是注册了一个 AnnotationAwareAspectJAutoProxyCreator 这个东西,用来创建代理的玩意儿。

先看看这个类的继承体系:

《【Spring源码】一个我们日常使用的AOP实现》

稍微看看左上角的 BeanPostProcessor,OK,是初始化容器的时候通过他来注入 AOP 内容。

解析Advisor配置的Bean

好了,那么环境初始化好了,MethodAop 这个 Advisor 也注册进去了,接下来就是运行的时候织入 Bean 的时候了。

根据调试查看,配置中的 Bean 是在 refresh() 方法中的 finishBeanFactoryInitialization(beanFactory); 这句话来织入并且生成代理对象的。

至于怎么创建对象的,之前有说过,现在要说的只不过是创建对象以后,使用 BeanPostProcessor 把建好的对象给替换掉。

所以直接点,来到 AbstractAutowireCapableBeanFactory#doCreateBean() 看看怎么操作的。(所以无论是不是配置中的 Bean,只要使用该方法来创建的,就是该 Bean 被织入的时机)

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
      // 初始化对象,这句话会调用BeanPostProcessor的before和After的方法
      // 织入的时机主要是在 postProcessAfterInitialization 方法中.
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

class AbstractAutowireCapableBeanFactory: 

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
 if (System.getSecurityManager() != null) {
  AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
   invokeAwareMethods(beanName, bean);
   return null;
  }, getAccessControlContext());
 }
 else {
  invokeAwareMethods(beanName, bean);
 }

 Object wrappedBean = bean;
 if (mbd == null || !mbd.isSynthetic()) {
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 }

 try {
  invokeInitMethods(beanName, wrappedBean, mbd);
 }
 catch (Throwable ex) {
  throw new BeanCreationException(
    (mbd != null ? mbd.getResourceDescription() : null),
    beanName, "Invocation of init method failed", ex);
 }
 if (mbd == null || !mbd.isSynthetic()) {
  // 应用Bean创建的后处理器,包装Bean
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 }

 return wrappedBean;
}

// 每个Bean创建就一顿循环 BeanPostProcessors,调用 BeanPostProcessor#postProcessAfterInitialization来处理实例
// 那么刚刚上面我们说过,环境初始化的时候,Spring偷偷放进去了一个 AnnotationAwareAspectJAutoProxyCreator
// 他其实就是一个BeanPostProcessors,所以不用说肯定在这个类里边处理
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  throws BeansException {

  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    Object current = processor.postProcessAfterInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}

分享个 debug 小技巧,因为是个循环,然后又很难看出来他循环到哪个类,稍微手抖了一下,又跳过了这个类又要重新开始 debug。所以我们可以使用 idea 提供的条件断点,我这里是使用 class 来比较,如果是我想要的这个 class 那么就停止在这个断点:

《【Spring源码】一个我们日常使用的AOP实现》

接下来进入看看:

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
 if (bean != null) {
  Object cacheKey = getCacheKey(bean.getClass(), beanName);
  // 提早曝光的代理引用,如果不是相同的,则调用 wrapIfNecessary 进行包装
  if (this.earlyProxyReferences.remove(cacheKey) != bean) {
   return wrapIfNecessary(bean, beanName, cacheKey);
  }
 }
 return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
  }
  // 这里通过 cacheKey 判断当前 Bean 是否之前记录不需要切入(使用 advisedBeans 存储)
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }
  // 1. 如果是 Advice/Pointcut 等 AOP 相关的类则跳过;
  // 2. BeanName以.ORIGINAL结尾的话,不做代理,如:com.mypackage.MyClass.ORIGINAL 
  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }

  // 在这里开始获取 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;
}

获取advisor

如果暂时对如何获取 advisor 没兴趣的话,可以先跳过,后面再回来看

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

这句话是用来获取 advisor 的,并且缓存起来项目中配置的 advisor

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
  Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
 if (advisors.isEmpty()) {
  return DO_NOT_PROXY;
 }
 return advisors.toArray();
}

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

List<Advisor> candidateAdvisors = findCandidateAdvisors(); 这句话使用来获取已经缓存起来了的所有 Advisors。因为在当前我们已经无法进入到怎么解析并缓存的问题上来了(因为已经缓存起来了),所以我们需要退回到前面的步骤中来。

解析Advisor

然而什么时候做的解析和缓存,我们刚刚在上一节中说了 initializeBean 会在创建所有 Bean 的时候调用所有 beanPostProcessor 的前置处理器。那我们来看看 AnnotationAwareAspectJAutoProxyCreator 的前置处理器做了什么,并且第一次调用该方法是什么时候:

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
 Object cacheKey = getCacheKey(beanClass, beanName);

 // 这里在前置的时候就开始记录哪些 Bean 需要织入,哪些不需要了
 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
  if (this.advisedBeans.containsKey(cacheKey)) {
   return null;
  }
  // 初始化第一个 Bean(在我这里是我那个配置类的初始化)的时候就开始调用 shouldSkip
  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;
}
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
  // 获取当前 BeanFactory 中所有的 advisor 对象,并且做缓存
  List<Advisor> candidateAdvisors = findCandidateAdvisors();
  for (Advisor advisor : candidateAdvisors) {
    if (advisor instanceof AspectJPointcutAdvisor &&
        ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
      return true;
    }
  }
  return super.shouldSkip(beanClass, beanName);
}

protected List<Advisor> findCandidateAdvisors() {
  // 先调用下面那个在父类的方法
  List<Advisor> advisors = super.findCandidateAdvisors();
  // 开始构建存在 BeanFactory 中的 Advisor
  if (this.aspectJAdvisorsBuilder != null) {
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
}
protected List<Advisor> findCandidateAdvisors() {
  Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
  // 通过一个 advisorRetrievalHelper 来获取所有的 advisor Bean
  return this.advisorRetrievalHelper.findAdvisorBeans();
}

advisorRetrievalHelper 是配置 auto-proxy 的时候,会被使用的一个类,他在 AnnotationAwareAspectJAutoProxyCreator 中传入一个 ConfigurableListableBeanFactory 作为参数调用构造器初始化。

所以,advisorRetrievalHelper 可以在当前容器中,查找所有的 BeanDefinition,并且取出是 AdvisorBean

接下来来看看这个方法做了什么事情:

/**
 * Find all eligible Advisor beans in the current bean factory,
 * ignoring FactoryBeans and excluding beans that are currently in creation.
 * @return the list of {@link org.springframework.aop.Advisor} beans
 * @see #isEligibleBean
 */
public List<Advisor> findAdvisorBeans() {
 // Determine list of advisor bean names, if not cached already.
 String[] advisorNames = this.cachedAdvisorBeanNames;
 if (advisorNames == null) {
  // Do not initialize FactoryBeans here: We need to leave all regular beans
  // uninitialized to let the auto-proxy creator apply to them!
  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));
    }
    catch (BeanCreationException ex) {
            .....
       continue;
      }
     }
     throw ex;
    }
   }
  }
 }
 return advisors;
}

OK,既然返回了一个空的集合,那么就来看看,后面做了什么事情了:

protected List<Advisor> findCandidateAdvisors() {
  // 先调用下面那个在父类的方法
  List<Advisor> advisors = super.findCandidateAdvisors();
  // 开始构建存在 BeanFactory 中的 Advisor
  if (this.aspectJAdvisorsBuilder != null) {
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
  List<String> aspectNames = this.aspectBeanNames;

  if (aspectNames == null) {
    synchronized (this) {
      // 因为 aspectBeanNames 现在是 NULL,所以进入开始初始化
      aspectNames = this.aspectBeanNames;
      if (aspectNames == null) {
        List<Advisor> advisors = new ArrayList<>();
        aspectNames = new ArrayList<>();
        // 获取 BeanFactory 中所有的 beanNames
        String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
          this.beanFactory, Object.class, true, false);
        // 二话不说就来了个循环
        for (String beanName : beanNames) {
          // 是否是个有资格的类?然而方法都是直接返回 true...也就是这一步永远不会进去
          // 感觉这个方法是个有故事的方法,先不看
          if (!isEligibleBean(beanName)) {
            continue;
          }
          // 这一步必须使用 getType 调用 getBean 可能会导致错误(那个Bean需要被织入但是太早初始化的
          // 话会导致没有织入成功)
          Class<?> beanType = this.beanFactory.getType(beanName);
          if (beanType == null) {
            continue;
          }
          // 这一步会判断类有没有被 @Aspect 修饰
          if (this.advisorFactory.isAspect(beanType)) {
            aspectNames.add(beanName);
              AspectMetadata amd = new AspectMetadata(beanType, beanName);
            // 根据 Advisor 是否可以为单例(这个是AOP定义的单例)来缓存 AOP 信息以便后面可以使用
            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
              // 构建 Advisor 工厂
              MetadataAwareAspectInstanceFactory factory =
                new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
              List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
              // 如果是单例(BeanFactory的单例)的 Bean,则直接缓存 Advisor 对象
              if (this.beanFactory.isSingleton(beanName)) {
                this.advisorsCache.put(beanName, classAdvisors);
              }
              else {
                this.aspectFactoryCache.put(beanName, factory);
              }
              advisors.addAll(classAdvisors);
            }
            else {
              // 每个目标对象或者每个对象都去织入.
              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;
      }
    }
  }

  // 下一次再调用该方法的时候,即可直接通过缓存中取出 Advisor 使用
  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;
}

获取所有的Advisor

刚刚我们来到这里:

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
 Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
 return DO_NOT_PROXY;
}
return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
 List<Advisor> candidateAdvisors = findCandidateAdvisors();// <-----
 // 获取装配当前 Bean 的 Advisor
 // 这一步其实就是获取 @Pointcut 中配置的装配规则来匹配所有的方法,我偷懒,先过
 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
 // 扩展Advisor
 extendAdvisors(eligibleAdvisors);
 if (!eligibleAdvisors.isEmpty()) {
   eligibleAdvisors = sortAdvisors(eligibleAdvisors);
 }
 return eligibleAdvisors;
}

现在在这个方法内部,已经获取我们自己配置的 MethodAop 对象了,但是下面还有个扩展,看看扩展了什么东西:

/**
    * Adds an {@link ExposeInvocationInterceptor} to the beginning of the advice chain.
    * These additional advices are needed when using AspectJ expression pointcuts
    * and when using AspectJ-style advice.
    */
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
  AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}

public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
  // Don't add advisors to an empty list; may indicate that proxying is just not required
  if (!advisors.isEmpty()) {
    boolean foundAspectJAdvice = false;
    for (Advisor advisor : advisors) {
      // 如果是 AspectJAdvice 则不添加
      if (isAspectJAdvice(advisor)) {
        foundAspectJAdvice = true;
        break;
      }
    }
    // 我们织入的方法中,都会添加一个 ExposeInvocationInterceptor 实例
    if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
      advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
      return true;
    }
  }
  return false;
}

这里有两个概念:

  1. AspectJAdvice:通过编译器织入 AOP 代码的一个框架;

  2. ExposeInvocationInterceptor:这是一个运行期织入时可以随时获取整个调用链的内置的 AOP 拦截器,如果在使用过程中需要获取调用链的话,可以通过 ExposeInvocationInterceptor.currentInvocation 来获取。SpringAOP 在织入的时候默认在第一个织入这个实例。

好了,走完全部,获取所有 advisors 的过程终于完成。

织入运行期对象

回到 postProcessAfterInitialization -> wrapIfNecessary 方法中来:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
  }
  // 这里通过 cacheKey 判断当前 Bean 是否之前记录不需要切入(使用 advisedBeans 存储)
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }
  // 1. 如果是 Advice/Pointcut 等 AOP 相关的类则跳过;
  // 2. BeanName以.ORIGINAL结尾的话,不做代理,如:com.mypackage.MyClass.ORIGINAL 
  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }

  // 在这里开始获取 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;
}

接下来就是开始创建代理对象了。创建对象有两种方式:cglibjdk代理,使用哪种方式取决于当前那个类有没有接口实现,如果是一个普通的类(没有实现接口的方式),则使用前者,否则用后者。

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

 if (!proxyFactory.isProxyTargetClass()) {
  if (shouldProxyTargetClass(beanClass, beanName)) {
   // 直接代理类实例(通过BeanDefinition配置的属性来判断)
   proxyFactory.setProxyTargetClass(true);
  }
  else {
   // 计算所有的接口设置到工厂,如果没有接口,同上直接代理实例
   evaluateProxyInterfaces(beanClass, proxyFactory);
  }
 }

 // 通过上一步获取的所有 advisors,过滤获取匹配的 advisors
 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
 proxyFactory.addAdvisors(advisors);
 proxyFactory.setTargetSource(targetSource);
 customizeProxyFactory(proxyFactory);

 proxyFactory.setFrozen(this.freezeProxy);
 if (advisorsPreFiltered()) {
  proxyFactory.setPreFiltered(true);
 }

 // 开始构建
 return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
  // 调用 DefaultAopProxyFactory 开始构建代理
    return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
  if (!this.active) {
    activate();
  }
  // getAopProxyFactory返回DefaultAopProxyFactory实例
  return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory#createAopProxy
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);
  }
}

createAopProxy 之后就是调用各自的实现 getProxy(classLoader)

Cglib

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
  if (logger.isTraceEnabled()) {
    logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
  }

  try {
    // 获取对象的实际类型
    Class<?> rootClass = this.advised.getTargetClass();
    Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

    // 如果已经是一个 cglib 对象的时候,获取其父级(实际类型)
    Class<?> proxySuperClass = rootClass;
    if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
      proxySuperClass = rootClass.getSuperclass();
      Class<?>[] additionalInterfaces = rootClass.getInterfaces();
      for (Class<?> additionalInterface : additionalInterfaces) {
        this.advised.addInterface(additionalInterface);
      }
    }

    // Validate the class, writing log messages as necessary.
    validateClassIfNecessary(proxySuperClass, classLoader);

    // 开始生成 cglib 对象
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
      enhancer.setClassLoader(classLoader);
      if (classLoader instanceof SmartClassLoader &&
          ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
        enhancer.setUseCache(false);
      }
    }
    enhancer.setSuperclass(proxySuperClass);
    // 这里Spring混合了自己的两个接口:SpringProxy和Advised
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        // 类加上 BySpringCGLIB 的标志
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
      types[x] = callbacks[x].getClass();
    }
    // fixedInterceptorMap only populated at this point, after getCallbacks call above
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
      this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);

    // 初始化代理对象
    return createProxyClassAndInstance(enhancer, callbacks);
  }
  catch (CodeGenerationException | IllegalArgumentException ex) {
    throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                                 ": Common causes of this problem include using a final class or a non-visible class",
                                 ex);
  }
  catch (Throwable ex) {
    // TargetSource.getTarget() failed
    throw new AopConfigException("Unexpected AOP exception", ex);
  }
}

OK,那让我们来看看调用的时候是什么情况:

现在我的对象已经变成 NoInterfaceService$$EnhancerBySpringCGLIB 类型了,那我在调用的时候不可否认的会进入到真实的对象里边去,此时我调用一下 test() 方法。

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

 private final AdvisedSupport advised;

 public DynamicAdvisedInterceptor(AdvisedSupport advised) {
  this.advised = advised;
 }

 @Override
 @Nullable
 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
  Object oldProxy = null;
  boolean setProxyContext = false;
  Object target = null;
  // 这里才是我的真实对象
  TargetSource targetSource = this.advised.getTargetSource();
  try {
   if (this.advised.exposeProxy) {
    // Make invocation available if necessary.
    oldProxy = AopContext.setCurrentProxy(proxy);
    setProxyContext = true;
   }
   // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
   target = targetSource.getTarget();
   Class<?> targetClass = (target != null ? target.getClass() : null);
   List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
   Object retVal;
   // 然后拿到了我们上面装配的 Advisor 执行链条
   if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
    // 如果链条是空的并且方法是共有的话,直接执行方法!
    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    retVal = methodProxy.invoke(target, argsToUse);
   }
   else {
    // 使用 CglibMethodInvocation 对象执行我们的方法
    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
   }
   // 如果方法有返回值,转换为指定的类型.
   retVal = processReturnType(proxy, target, method, retVal);
   return retVal;
  }
  finally {
   if (target != null && !targetSource.isStatic()) {
    targetSource.releaseTarget(target);
   }
   if (setProxyContext) {
    // Restore old proxy.
    AopContext.setCurrentProxy(oldProxy);
   }
  }
 }
  // 省略其他代码
}

OK,接下来看看 CglibMethodInvocation#proceed() 做了什么事:

CglibMethodInvocation#proceed:
@Override
@Nullable
public Object proceed() throws Throwable {
  try {
    return super.proceed();
  }
  catch (RuntimeException ex) {
    throw ex;
  }
  catch (Exception ex) {
    if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) {
      throw ex;
    }
    else {
      throw new UndeclaredThrowableException(ex);
    }
  }
}
ReflectiveMethodInvocation#proceed:
@Override
@Nullable
public Object proceed() throws Throwable {
  // 当在MethodAop中调用 Object proceed = joinPoint.proceed(); 的时候,此处会直接调用切入点的那个方法,就是当前的拦截器index === 最后一个的时候,是直接调用目标方法。
  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);
  }
}

此时,第一个切入类是 SpringExposeInvocationInterceptor,直接走到下面的 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
  // 保存一个老的调用链
  MethodInvocation oldInvocation = invocation.get();
  // 当前调用链给了新的
  invocation.set(mi);
  try {
    // 调用下一个拦截器
    return mi.proceed();
  }
  finally {
    // 恢复回去
    invocation.set(oldInvocation);
  }
}

重新进来还是调用 ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this) 这段代码:

此时进来的是:

AspectJAroundAdvice#invoke:
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;
  // 这个参数就是我们写在 around 方法参数中的那个
  // 此时我们的方法已经被织入在这个类的方法里边去
  // 所以只要执行我们的 around 方法就是变相执行我们真实对象的方法了。
  ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
  JoinPointMatch jpm = getJoinPointMatch(pmi);
  return invokeAdviceMethod(pjp, jpm, null, null);
}
// As above, but in this case we are given the join point.
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
                                    @Nullable Object returnValue, @Nullable Throwable t) throws Throwable {

  return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
  Object[] actualArgs = args;
  if (this.aspectJAdviceMethod.getParameterCount() == 0) {
    actualArgs = null;
  }
  try {
    ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
    // 使用反射直接调用advisor中的方法
    return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
  }
  catch (IllegalArgumentException ex) {
    throw new AopInvocationException("Mismatch on arguments to advice method [" +
                                     this.aspectJAdviceMethod + "]; pointcut expression [" +
                                     this.pointcut.getPointcutExpression() + "]", ex);
  }
  catch (InvocationTargetException ex) {
    throw ex.getTargetException();
  }
}

jdk动态代理

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
 if (logger.isTraceEnabled()) {
  logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
 }
 // 同样获取到所有的接口
 // 这次 Spring 混入了三个:SpringProxy、Advised 和 DecoratingProxy
 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
 // 获取接口中定义的 equals 方法
 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
 // 通过直接调用 jdk 的 Proxy 创建代理对象
 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

调用的时候则是使用 jdk 的 invoke 方式进行调用:

@Override
@Nullable
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 {
  if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
   // The target does not implement the equals(Object) method itself.
   return equals(args[0]);
  }
  else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
   // The target does not implement the hashCode() method itself.
   return hashCode();
  }
  else if (method.getDeclaringClass() == DecoratingProxy.class) {
   // There is only getDecoratedClass() declared -> dispatch to proxy config.
   return AopProxyUtils.ultimateTargetClass(this.advised);
  }
  else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
   // Service invocations on ProxyConfig with the proxy config...
   return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
  }

  Object retVal;

  // 上面均是特殊方法的代理形式,直接走到这里
  if (this.advised.exposeProxy) {
   // Make invocation available if necessary.
   oldProxy = AopContext.setCurrentProxy(proxy);
   setProxyContext = true;
  }

  // Get as late as possible to minimize the time we "own" the target,
  // in case it comes from a pool.
  target = targetSource.getTarget();
  Class<?> targetClass = (target != null ? target.getClass() : null);

  // 获取AOP拦截链
  List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

  // Check whether we have any advice. If we don't, we can fallback on direct
  // reflective invocation of the target, and avoid creating a MethodInvocation.
  if (chain.isEmpty()) {
   // We can skip creating a MethodInvocation: just invoke the target directly
   // Note that the final invoker must be an InvokerInterceptor so we know it does
   // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
   Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
   retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  }
  else {
   // 这一步就跟上面一样了
   MethodInvocation invocation =
     new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
   // Proceed to the joinpoint through the interceptor 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())) {
   // Special case: it returned "this" and the return type of the method
   // is type-compatible. Note that we can't help if the target sets
   // a reference to itself in another returned object.
   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;
 }
 finally {
  if (target != null && !targetSource.isStatic()) {
   // Must have come from TargetSource.
   targetSource.releaseTarget(target);
  }
  if (setProxyContext) {
   // Restore old proxy.
   AopContext.setCurrentProxy(oldProxy);
  }
 }
}

AOP中this的问题

这个问题是我印象最深的一个问题,曾经使用了 spring-cache,预想着通过注解,就可以解决缓存的问题,实在是一件很有感觉的事情,然而,在清理的时候,并不是这么简单…经常遇到我明明注解已经写了,但是就是没有给我清理的问题。后面就直接没有使用了。


@CacheEvict(value="userCache",key="#u.getUID()") pubic void updateUser(User u) { // ....逻辑 //调用其他方法让其重新缓存 userOfUID(u.getUID); } @Cacheable(value = "userCache",key="#result.getUID()") pubic User userOfUID(String uid) { userDao.userOfUID(uid); }

然而走完 updateUser 缓存直接没了,并没有帮我刷新。

这个确实是 AOP 中模糊了 this 指向的问题。

我们通过刚刚的例子可以看到,其实 AOP 生效的时机是你从 BeanFactory 中拿到 Bean 的时候,因为这个时候你拿到的就是一个代理对象,那么会执行 AOPAdvisor 中定义的方法。但是如果我们直接在我们的类中使用 this 的时候,其实指向的是我们自己的类实例,没有走 Spring 外部的逻辑。

那咋办呢…

重点就在于怎么拿到 Spring 的代理对象!参考资料

通过配置 exposeProxy ,然后通过 ((UserService) AopContext.currentProxy()).userOfUID(); 来调用。

配置:

注解:@EnableAspectJAutoProxy(proxyTargteClass = true, exposeProxy = true)

xml<aop:aspectj-autoproxy expose-proxy="true"/>

那我就比较懒(sao)了…「好了 还是不要这么用吧…」

public class UserServiceImpl implements UserService {

  @Lazy
  @Autowired
  private UserService userService;

  @CacheEvict(value="userCache",key="#u.getUID()")
    pubic void updateUser(User u) {
    // ....逻辑
    //调用其他方法让其重新缓存
    userService.userOfUID(u.getUID);
  }

  @Cacheable(value = "userCache",key="#result.getUID()")
  pubic User userOfUID(String uid) {
    userDao.userOfUID(uid);
  }

}

点赞