# 源码解析:AOP

通过schema形式使用spring aop时,spring提供了相应的拓展,可以解析自定义的标签。下面是基于schema使用spring aop的一个示例:

<?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:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    <aop:config>
        <aop:aspect id="countAgeCalls" ref="countingAdvice">
            <aop:pointcut id="pc" expression="execution(* getAge())"/>
            <aop:before pointcut-ref="pc" method="myBeforeAdvice" />
            <aop:after pointcut-ref="pc" method="myAfterAdvice" />
            <aop:after-returning pointcut-ref="pc" method="myAfterReturningAdvice" returning="age"/>
            <aop:after-throwing pointcut-ref="pc" method="myAfterThrowingAdvice" throwing="ex"/>
            <aop:around pointcut-ref="pc" method="myAroundAdvice"/>
        </aop:aspect>
    </aop:config>

    <bean id="getNameCounter" class="org.springframework.tests.aop.advice.CountingBeforeAdvice"/>

    <bean id="getAgeCounter" class="org.springframework.tests.aop.advice.CountingBeforeAdvice"/>

    <bean id="testBean" class="org.springframework.tests.sample.beans.TestBean"/>

    <bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>

</beans>

解析aop标签

解析自定义标签需要实现NamespaceHandler接口,spring内部提供的解析aop标签的实现是AopNamespaceHandler

public class AopNamespaceHandler extends NamespaceHandlerSupport {

   /**
    * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
    * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
    * and '{@code scoped-proxy}' tags.
    */
   @Override
   public void init() {
      // In 2.0 XSD as well as in 2.1 XSD.
      registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
      registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
      registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

      // Only in 2.0 XSD: moved to context namespace as of 2.1
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
   }

}

init()方法中可以看出,其针对各种标签都有相应的解析器。下面让我们分析一下最常用的<aop:config>以及<aop:aspectj-autoproxy>标签。

首先让我们进入ConfigBeanDefinitionParser类:

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
   CompositeComponentDefinition compositeDef =
         new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
   parserContext.pushContainingComponent(compositeDef);

   // 配置自动代理的构建器
   configureAutoProxyCreator(parserContext, element);

   // 获取子标签
   List<Element> childElts = DomUtils.getChildElements(element);
   for (Element elt: childElts) {
      // 获取标签名
      String localName = parserContext.getDelegate().getLocalName(elt);
      // 针对pointcut, advisor, aspect执行对应的解析
      if (POINTCUT.equals(localName)) {
         parsePointcut(elt, parserContext);
      }
      else if (ADVISOR.equals(localName)) {
         parseAdvisor(elt, parserContext);
      }
      else if (ASPECT.equals(localName)) {
         parseAspect(elt, parserContext);
      }
   }

   parserContext.popAndRegisterContainingComponent();
   return null;
}

看到自动代理的构建器可能会比较疑惑,这个构建器有什么用?让我们思考一下如何对bean进行代理。Spring提供了BeanPostProcessor及其子接口,可以在bean实例化之前对其进行修改,当然spring已经帮我们实现了自动化,不需要我们手动去注册这个BeanPostProcessor,因此这个构建器的功能便是将其注册到BeanFactory,以便之后创建bean的时候调用。

配置自动代理构建器

配置自动代理构建器共分为三步:

  1. 注册或者升级internalAutoProxyCreator bean
  2. 设置proxy-target-classexpose-proxy
  3. 注册组件
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
   AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}

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

   // 注册或者升级internalAutoProxyCreator
   // 优先级 AnnotationAwareAspectJAutoProxyCreator -> AspectJAwareAdvisorAutoProxyCreator -> InfrastructureAdvisorAutoProxyCreator
   // 默认选用AspectJAwareAdvisorAutoProxyCreator
   BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
         parserContext.getRegistry(), parserContext.extractSource(sourceElement));
   // 设置proxy-target-class和expose-proxy
   useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
   registerComponentIfNecessary(beanDefinition, parserContext);
}

1. 注册或者升级bean internalAutoProxyCreator

spring内部规定构造器的beanName为internalAutoProxyCreator,如果用户想要手动指定构建器,那么需要使用此名称作为beanName。

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

   return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(
      Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

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

   // 如果用户手动指定了internalAutoProxyCreator,那么检查是否需要升级
   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
      BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
      // 如果手动指定的bean的类型不是AspectJAwareAdvisorAutoProxyCreator,尝试进行升级
      if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
         // 获取用户bean类型的优先级以及AspectJAwareAdvisorAutoProxyCreator的优先级
         int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
         int requiredPriority = findPriorityForClass(cls);
         // 使用优先级更高的构建器
         if (currentPriority < requiredPriority) {
            apcDefinition.setBeanClassName(cls.getName());
         }
      }
      return null;
   }

   // 配置RootBeanDefinition并注册
   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;
}

当然,只能指定固定的三个构建器,无法自定义构建器。可选用的构建器及优先级如下:

private static int findPriorityForClass(Class<?> clazz) {
   return APC_PRIORITY_LIST.indexOf(clazz);
}

private static int findPriorityForClass(@Nullable String className) {
   for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
      Class<?> clazz = APC_PRIORITY_LIST.get(i);
      if (clazz.getName().equals(className)) {
         return i;
      }
   }
   throw new IllegalArgumentException(
         "Class name [" + className + "] is not a known auto-proxy creator class");
}

private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

static {
   // Set up the escalation list...
   APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
   APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
   APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}

2. 设置proxy-target-classexpose-proxy

spring aop的代理方式分为两种:jdk接口代理和cglib类代理。如果将proxy-target-class属性设为true,那么将强制使用类代理。

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
   if (sourceElement != null) {
      // proxy-target-class
      boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
      if (proxyTargetClass) {
         AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
      }
      // expose-proxy
      boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
      if (exposeProxy) {
         AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
      }
   }
}

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
      BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
      definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
   }
}

如果proxy-target-classexpose-proxy设置为true,那么将其设置到BeanDefinition中,创建bean实例时设置此属性。

3. 注册组件

最后注册组件。这一步spring内部是一个空实现,留待拓展。

private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
   if (beanDefinition != null) {
      parserContext.registerComponent(
            new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
   }
}

解析子标签

配置完自动代理构建器后,需要解析pointcut, advisor, aspect等子标签。

解析pointcut子标签

pointcut子标签的形式如下所示:

<aop:pointcut id="businessService"
            expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>

解析过程如下:

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

   AbstractBeanDefinition pointcutDefinition = null;

   try {
      this.parseState.push(new PointcutEntry(id));
      // 构造pointcut BeanDefinition
      pointcutDefinition = createPointcutDefinition(expression);
      pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));

      // 将此pointcut BeanDefinition注册到容器中
      String pointcutBeanName = id;
      if (StringUtils.hasText(pointcutBeanName)) {
         parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
      }
      else {
         pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
      }

      parserContext.registerComponent(
            new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
   }
   finally {
      this.parseState.pop();
   }

   return pointcutDefinition;
}

protected AbstractBeanDefinition createPointcutDefinition(String expression) {
   // 表示pointcut的类是AspectJExpressionPointcut
   RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
   beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
   beanDefinition.setSynthetic(true);
   beanDefinition.getPropertyValues().add(EXPRESSION, expression);
   return beanDefinition;
}

如果没有设置id属性或者id属性的值为空白符,那么spring将会自动为其生成一个合法名称。

解析aspect子标签

<aop:aspect id="myAspect" ref="aBean">

        <aop:pointcut id="businessService"
            expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>

        <aop:before pointcut-ref="businessService" method="monitor"/>

        <aop:declare-parents
            types-matching="com.xzy.myapp.service.*+"
            implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
            default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
        ...
</aop:aspect>

aspect标签下可以定义pointcut, before, after-returning, after-throwing, after, around, declare-parents标签。

关于这几个标签的更多信息,请查看下面提供的官方文档链接:

了解了它们各自的作用后,让我们开始解析过程:

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

   try {
      this.parseState.push(new AspectEntry(aspectId, aspectName));
      List<BeanDefinition> beanDefinitions = new ArrayList<>();
      List<BeanReference> beanReferences = new ArrayList<>();

      // 获取declare-parents子标签
      List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
      // 如果存在,执行相应解析
      for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
         Element declareParentsElement = declareParents.get(i);
         beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
      }

      // We have to parse "advice" and all the advice kinds in one loop, to get the
      // ordering semantics right.
      NodeList nodeList = aspectElement.getChildNodes();
      boolean adviceFoundAlready = false;
      // 解析advice子标签
      for (int i = 0; i < nodeList.getLength(); i++) {
         Node node = nodeList.item(i);
         if (isAdviceNode(node, parserContext)) {
            if (!adviceFoundAlready) {
               adviceFoundAlready = true;
               if (!StringUtils.hasText(aspectName)) {
                  parserContext.getReaderContext().error(
                        "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",
                        aspectElement, this.parseState.snapshot());
                  return;
               }
               beanReferences.add(new RuntimeBeanReference(aspectName));
            }
            AbstractBeanDefinition advisorDefinition = parseAdvice(
                  aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
            beanDefinitions.add(advisorDefinition);
         }
      }

      AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
            aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
      parserContext.pushContainingComponent(aspectComponentDefinition);

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

      parserContext.popAndRegisterContainingComponent();
   }
   finally {
      this.parseState.pop();
   }
}

方法较为简单清晰,对每个类型的标签都尝试去解析。

解析declare-parents

private AbstractBeanDefinition parseDeclareParents(Element declareParentsElement, ParserContext parserContext) {
   // 表示declare-parents的类为DeclareParentsAdvisor
   BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DeclareParentsAdvisor.class);
   // 获取implement-interface和types-matching属性作为构造方法参数
   builder.addConstructorArgValue(declareParentsElement.getAttribute(IMPLEMENT_INTERFACE));
   builder.addConstructorArgValue(declareParentsElement.getAttribute(TYPE_PATTERN));

   // 获取default-impl和delegate-ref属性,如果存在作为构造方法参数,这两个属性必须指定一个且仅一个
   String defaultImpl = declareParentsElement.getAttribute(DEFAULT_IMPL);
   String delegateRef = declareParentsElement.getAttribute(DELEGATE_REF);

   if (StringUtils.hasText(defaultImpl) && !StringUtils.hasText(delegateRef)) {
      builder.addConstructorArgValue(defaultImpl);
   }
   else if (StringUtils.hasText(delegateRef) && !StringUtils.hasText(defaultImpl)) {
      builder.addConstructorArgReference(delegateRef);
   }
   else {
      parserContext.getReaderContext().error(
            "Exactly one of the " + DEFAULT_IMPL + " or " + DELEGATE_REF + " attributes must be specified",
            declareParentsElement, this.parseState.snapshot());
   }

   AbstractBeanDefinition definition = builder.getBeanDefinition();
   definition.setSource(parserContext.extractSource(declareParentsElement));
   // 自动生成一个beanName并注册
   parserContext.getReaderContext().registerWithGeneratedName(definition);
   return definition;
}

解析advice

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

      // create the method factory bean
      RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
      methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
      methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
      methodDefinition.setSynthetic(true);

      // create instance factory definition
      RootBeanDefinition aspectFactoryDef =
            new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
      aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
      aspectFactoryDef.setSynthetic(true);

      // register the pointcut
      AbstractBeanDefinition adviceDef = createAdviceDefinition(
            adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
            beanDefinitions, beanReferences);

      // configure the 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));
      }

      // register the final advisor
      parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

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

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

   // 根据不同的advice类型获取对应的类
   RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
   adviceDefinition.setSource(parserContext.extractSource(adviceElement));

   // 设置aspectName和declarationOrder属性
   adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
   adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);

   if (adviceElement.hasAttribute(RETURNING)) {
      adviceDefinition.getPropertyValues().add(
            RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
   }
   if (adviceElement.hasAttribute(THROWING)) {
      adviceDefinition.getPropertyValues().add(
            THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
   }
   if (adviceElement.hasAttribute(ARG_NAMES)) {
      adviceDefinition.getPropertyValues().add(
            ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
   }

   ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
   cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);

   // 解析pointcut-ref或者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);
   }

   cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);

   return adviceDefinition;
}

private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
   String elementName = parserContext.getDelegate().getLocalName(adviceElement);
   if (BEFORE.equals(elementName)) {
      return AspectJMethodBeforeAdvice.class;
   }
   else if (AFTER.equals(elementName)) {
      return AspectJAfterAdvice.class;
   }
   else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
      return AspectJAfterReturningAdvice.class;
   }
   else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
      return AspectJAfterThrowingAdvice.class;
   }
   else if (AROUND.equals(elementName)) {
      return AspectJAroundAdvice.class;
   }
   else {
      throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
   }
}

表示advice的类都实现了Advice接口。

解析advisor子标签

advisor是使用切面的另一种形式,它是独属于spring aop的概念,是aspect的一个更细化的形式,它只包含一个advice。更多信息请查看此处

<aop:config>

    <aop:pointcut id="businessService"
        expression="execution(* com.xyz.myapp.service.*.*(..))"/>

    <aop:advisor
        pointcut-ref="businessService"
        advice-ref="tx-advice"/>

</aop:config>

<tx:advice id="tx-advice">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

解析过程如下:

private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
   // 构造BeanDefinition
   AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
   String id = advisorElement.getAttribute(ID);

   try {
      this.parseState.push(new AdvisorEntry(id));
      // 注册到容器
      String advisorBeanName = id;
      if (StringUtils.hasText(advisorBeanName)) {
         parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
      }
      else {
         advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
      }

      // 解析pointcut属性
      Object pointcut = parsePointcutProperty(advisorElement, parserContext);
      if (pointcut instanceof BeanDefinition) {
         advisorDef.getPropertyValues().add(POINTCUT, pointcut);
         parserContext.registerComponent(
               new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
      }
      else if (pointcut instanceof String) {
         advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
         parserContext.registerComponent(
               new AdvisorComponentDefinition(advisorBeanName, advisorDef));
      }
   }
   finally {
      this.parseState.pop();
   }
}

private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
   // advisor的表示类为DefaultBeanFactoryPointcutAdvisor
   RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
   advisorDefinition.setSource(parserContext.extractSource(advisorElement));

   // 获取`advice-ref`属性
   String adviceRef = advisorElement.getAttribute(ADVICE_REF);
   if (!StringUtils.hasText(adviceRef)) {
      parserContext.getReaderContext().error(
            "'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot());
   }
   else {
      advisorDefinition.getPropertyValues().add(
            ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
   }

   // 尝试设置order属性
   if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
      advisorDefinition.getPropertyValues().add(
            ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY));
   }

   return advisorDefinition;
}

各个标签的解析过程都比较简单,参照注释已经足以理解,不多赘述。

至此,aop:config标签已经全部解析完成,让我们总结一下其中涉及到的各种定义。

  • 自动代理构建器:beanName为internalAutoProxyCreator,beanClass为AspectJAwareAdvisorAutoProxyCreator
  • pointcut:beanClass为AspectJExpressionPointcut
  • declare-parents:beanClass为DeclareParentsAdvisor
  • advice:beanClass为AspectJPointcutAdvisor
  • before:beanClass为AspectJMethodBeforeAdvice
  • after-returning:beanClass为AspectJAfterReturningAdvice
  • after-throwing:beanClass为AspectJAfterThrowingAdvice
  • after:beanClass为AspectJAfterAdvice
  • around:beanClass为AspectJAroundAdvice
  • advisor:beanClass为DefaultBeanFactoryPointcutAdvisor

除了<aop:config>标签,另一个常用标签为<aop:aspectj-autoproxy>,它是用来解析基于注解的Aop定义。让我们看一下AspectJAutoProxyBeanDefinitionParser类的parse方法。

public BeanDefinition parse(Element element, ParserContext parserContext) {
   AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
   extendBeanDefinition(element, parserContext);
   return null;
}

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

   // 注册AnnotationAwareAspectJAutoProxyCreator
   BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
         parserContext.getRegistry(), parserContext.extractSource(sourceElement));
   useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
   registerComponentIfNecessary(beanDefinition, parserContext);
}

配置自动代理构建器与<aop:config>类似,不过使用了优先级更高的AnnotationAwareAspectJAutoProxyCreator

当启动此配置时,默认检查所有使用了@AspectJ注解的类。为了提供更精细化的控制,spring提供了<aop:include>标签,你可以在name属性中使用正则表达式来指定检查哪些使用了@AspectJ注解的类。

<aop:aspectj-autoproxy>
    <aop:include name="" />
</aop:aspectj-autoproxy>
private void extendBeanDefinition(Element element, ParserContext parserContext) {
   BeanDefinition beanDef =
         parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
   if (element.hasChildNodes()) {
      addIncludePatterns(element, parserContext, beanDef);
   }
}

private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
   ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
   NodeList childNodes = element.getChildNodes();
   // 检查所有子节点,获取其name属性
   for (int i = 0; i < childNodes.getLength(); i++) {
      Node node = childNodes.item(i);
      if (node instanceof Element) {
         Element includeElement = (Element) node;
         TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
         valueHolder.setSource(parserContext.extractSource(includeElement));
         includePatterns.add(valueHolder);
      }
   }
   // 设置到includePatterns属性中
   if (!includePatterns.isEmpty()) {
      includePatterns.setSource(parserContext.extractSource(element));
      beanDef.getPropertyValues().add("includePatterns", includePatterns);
   }
}

使用代理增强bean

之前说过Spring提供了BeanPostProcessor,可以在bean实例化之前对其进行处理,因此可以通过这种方式实现代理,让我们看一下自动代理构建器AspectJAwareAdvisorAutoProxyCreator的继承层次:

AspectJAwareAdvisorAutoProxyCreator.png

可以发现它确实实现了BeanPostProcessor接口。

Spring创建bean的其中一段过程如下,在doCreateBean也就是真正的创建bean方法调用之前会先调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(Class<?>, String)方法,执行用户或者Spring自定义的一些操作。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   // 从配置元数据中解析此bean的class
   // 因为配置元数据中只能保存String信息,所以需要使用类加载器加载这个类,并返回一个Class<?>对象
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   // 记录到缓存中,下次就不需要再从String中解析class了
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   // 对lookup-method,replaced-method方法注入进行预处理
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      // 调用后置处理器
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   // 创建bean实例
   Object beanInstance = doCreateBean(beanName, mbdToUse, args);
   if (logger.isDebugEnabled()) {
      logger.debug("Finished creating instance of bean '" + beanName + "'");
   }
   return beanInstance;
}

resolveBeforeInstantiation方法就是调用后置处理器的方法:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   // mbd.beforeInstantiationResolved属性默认是被初始化为null的
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      // 如果这个bean factory中注册了一个InstantiationAwareBeanPostProcessor后置处理器
      // InstantiationAwareBeanPostProcessor继承自BeanPostProcessor
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
         Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
         if (result != null) {
            return result;
         }
      }
   }
   return null;
}

了解了Spring创建bean的部分过程后,我们就可以正式开始探索AspectJAwareAdvisorAutoProxyCreator是如何代理bean的了。

首先让我们看一下postProcessBeforeInstantiation方法:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
   // 构造缓存key,一般为bean的名称
   Object cacheKey = getCacheKey(beanClass, beanName);

   // 执行一些过滤操作,对于某些bean不进行代理
   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;
      }
   }

   // 默认没有自定义的TargetSource
   // 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;
}

如果提供了自定义的TargetSource,那会尝试根据此TargetSource生成代理并返回。这个接口是Spring框架的内部接口,开发者不需要直接与其打交道,所以postProcessBeforeInstantiation方法最终返回null,进行正常的bean创建流程。

TargetSource的主要作用是为代理提供源对象,因此执行完增强逻辑后,代理对象可以把方法调用转发到源对象上,形成一个完整的调用链。

Spring默认使用SingletonTargetSource,每一次请求代理对象时,SingletonTargetSource都会返回同一个源对象,这也是我们所期待的。你也可以自定义TargetSource或者使用Spring提供的其他TargetSource,但是你的bean需要是prototype才可以发挥它们的特性。

关于TargetSource的更多信息,请查看Spring官方文档6.9. Using TargetSource Implementations

除了postProcessBeforeInstantiation方法外,在bean的创建过程中还会调用其他后置处理方法,如下所示:

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
   return true;
}

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
   return bean;
}

/**
 * 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);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

上面三个方法中,只有postProcessAfterInitialization方法进行了一定的逻辑处理,wrapIfNecessary方法便是进行将bean包装为代理的任务。

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;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have advice.
   // 获取用于增强此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;
}

包装共分为两步,首先需要找到用于增强bean的advice或者advisor,然后构建代理对象将它们融合到一起。

寻找Advisor

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) {
   // 寻找所有的advisor
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   // 选择能到应用到此bean上的advisor
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   // 拓展操作,留待子类实现
   extendAdvisors(eligibleAdvisors);
   // 排序可用的advisor
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

寻找操作共四步:

  1. 寻找所有的Advisor
  2. 选择能到应用到此bean上的Advisor
  3. 拓展Advisor
  4. 排序可用的Advisor

寻找所有的Advisor

这一步较为简单,从BeanFactory中寻找所有类型为Advisor的bean,并且实例化它们即可。

protected List<Advisor> findCandidateAdvisors() {
   Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
   return this.advisorRetrievalHelper.findAdvisorBeans();
}

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

   // 创建Advisor bean
   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) {
               Throwable rootCause = ex.getMostSpecificCause();
               if (rootCause instanceof BeanCurrentlyInCreationException) {
                  BeanCreationException bce = (BeanCreationException) rootCause;
                  String bceBeanName = bce.getBeanName();
                  if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                     if (logger.isTraceEnabled()) {
                        logger.trace("Skipping advisor '" + name +
                              "' with dependency on currently created bean: " + ex.getMessage());
                     }
                     // Ignore: indicates a reference back to the bean we're trying to advise.
                     // We want to find advisors other than the currently created bean itself.
                     continue;
                  }
               }
               throw ex;
            }
         }
      }
   }
   return advisors;
}

在之前解析<aop:config>标签时,一共生成了三种Advisor

  • declare-parents:beanClass为DeclareParentsAdvisor
  • advisor:beanClass为DefaultBeanFactoryPointcutAdvisor
  • advice:beanClass为AspectJPointcutAdvisor

因此,上一步获取到Advisor便是配置文件中的declare-parentsadvisor以及各种advice

选择能到应用到此bean上的Advisor

找到所有的Advisor后,需要根据其types-matching(declare-parents)或者pointcut(advisor,advice)过滤出可用的Advisor

protected List<Advisor> findAdvisorsThatCanApply(
      List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
   if (candidateAdvisors.isEmpty()) {
      return candidateAdvisors;
   }
   List<Advisor> eligibleAdvisors = new ArrayList<>();
   // 如果是引介Advisor(比如declare-parents)并且可以应用到此bean上
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
         eligibleAdvisors.add(candidate);
      }
   }
   boolean hasIntroductions = !eligibleAdvisors.isEmpty();
   // 查找其他Advisor
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor) {
         // already processed
         continue;
      }
      if (canApply(candidate, clazz, hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}

由于这三种Advisor的匹配方式不同,所以需要在不同方法种判断。其中DefaultBeanFactoryPointcutAdvisorAspectJPointcutAdvisor都使用pointcut匹配。

public static boolean canApply(Advisor advisor, Class<?> targetClass) {
   return canApply(advisor, targetClass, false);
}

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
   // 匹配declare-parents
   if (advisor instanceof IntroductionAdvisor) {
      return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
   }
   else if (advisor instanceof PointcutAdvisor) {
      // 匹配advisor和advice
      PointcutAdvisor pca = (PointcutAdvisor) advisor;
      return canApply(pca.getPointcut(), targetClass, hasIntroductions);
   }
   else {
      // It doesn't have a pointcut so we assume it applies.
      return true;
   }
}

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
   Assert.notNull(pc, "Pointcut must not be null");
   if (!pc.getClassFilter().matches(targetClass)) {
      return false;
   }

   MethodMatcher methodMatcher = pc.getMethodMatcher();
   if (methodMatcher == MethodMatcher.TRUE) {
      // No need to iterate the methods if we're matching any method anyway...
      return true;
   }

   IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
   if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
      introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
   }

   Set<Class<?>> classes = new LinkedHashSet<>();
   if (!Proxy.isProxyClass(targetClass)) {
      classes.add(ClassUtils.getUserClass(targetClass));
   }
   classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

   for (Class<?> clazz : classes) {
      Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
      for (Method method : methods) {
         if (introductionAwareMethodMatcher != null ?
               introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
               methodMatcher.matches(method, targetClass)) {
            return true;
         }
      }
   }

   return false;
}

其中declare-parents使用的是类匹配,而advisor则是通过pointcut使用方法匹配。具体的匹配逻辑此处不进行分析,感兴趣可以自行探索。

拓展Advisor

拓展操作一般留待子类实现,此处Spring增加了一个适配Advisor,以使得AspectJAdvice可以正常工作,此举是因为aspectj的部分特性决定的。

@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
   // 如果使用到了AspectJAdvice,那么需要增加一个特殊的advisor来适配
   if (!advisors.isEmpty()) {
      boolean foundAspectJAdvice = false;
      for (Advisor advisor : advisors) {
         // Be careful not to get the Advice without a guard, as this might eagerly
         // instantiate a non-singleton AspectJ aspect...
         if (isAspectJAdvice(advisor)) {
            foundAspectJAdvice = true;
            break;
         }
      }
      if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
         advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
         return true;
      }
   }
   return false;
}

/**
 * Determine whether the given Advisor contains an AspectJ advice.
 * @param advisor the Advisor to check
 */
private static boolean isAspectJAdvice(Advisor advisor) {
   return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
         advisor.getAdvice() instanceof AbstractAspectJAdvice ||
         (advisor instanceof PointcutAdvisor &&
               ((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
}

isAspectJAdvice方法较为复杂,涉及到了多个判断。如果你的aop:advisor使用的自定义advice-refAbstractAspectJAdvice的子类,那么便算是AspectJAdvice;同时,所有的beforeafteradvice默认全都是AbstractAspectJAdvice类型。目前的Poincut的默认实现全都是AspectJExpressionPointcut,当然,你也可以使用Spring提供的其他类型的Pointcut来构造你的advisor

简而言之,使用spring默认的aop配置,isAspectJAdvice的返回值将会为true。

排序可用的advisor

排序主要通过两种方式,第一种是实现Ordered或者PriorityOrdered接口,调用getOrder()方法获取值。此处只建议实现Ordered接口,由于之前在拓展Advisor部分提到为了兼容AspectJAdvice,spring会加入一个内置的Advisor来进行适配,这个Advisor实现了PriorityOrdered接口,希望将其作为第一个Advisor。因此,除非你比较熟悉这一方面的内容,否则不要实现PriorityOrdered接口,以防造成意料之外的结果。

第二种方法是使用@Order或者@Priority注解。

如果两种方法都没有使用,那么返回最低优先级。另外,这两种方法的优先级为:Ordered -> @Order -> @Priority

protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
   AnnotationAwareOrderComparator.sort(advisors);
   return advisors;
}

public static void sort(List<?> list) {
   if (list.size() > 1) {
      list.sort(INSTANCE);
   }
}

public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();

public int compare(@Nullable Object o1, @Nullable Object o2) {
   return doCompare(o1, o2, null);
}

private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
   // ExposeInvocationInterceptor实现了PriorityOrdered,它永远作为advisor列表的第一个
   boolean p1 = (o1 instanceof PriorityOrdered);
   boolean p2 = (o2 instanceof PriorityOrdered);
   if (p1 && !p2) {
      return -1;
   }
   else if (p2 && !p1) {
      return 1;
   }

   // 获取顺序
   int i1 = getOrder(o1, sourceProvider);
   int i2 = getOrder(o2, sourceProvider);
   return Integer.compare(i1, i2);
}

private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
   Integer order = null;
   if (obj != null && sourceProvider != null) {
      Object orderSource = sourceProvider.getOrderSource(obj);
      if (orderSource != null) {
         if (orderSource.getClass().isArray()) {
            Object[] sources = ObjectUtils.toObjectArray(orderSource);
            for (Object source : sources) {
               order = findOrder(source);
               if (order != null) {
                  break;
               }
            }
         }
         else {
            order = findOrder(orderSource);
         }
      }
   }
   // 调用getOrder(obj)方法
   return (order != null ? order : getOrder(obj));
}

protected int getOrder(@Nullable Object obj) {
   if (obj != null) {
      Integer order = findOrder(obj);
      if (order != null) {
         return order;
      }
   }
   return Ordered.LOWEST_PRECEDENCE;
}

@Nullable
protected Integer findOrder(Object obj) {
   return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}


protected Integer findOrder(Object obj) {
   Integer order = super.findOrder(obj);
   if (order != null) {
      return order;
   }
   return findOrderFromAnnotation(obj);
}

@Nullable
private Integer findOrderFromAnnotation(Object obj) {
   AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
   MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
   Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
   if (order == null && obj instanceof DecoratingProxy) {
      return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
   }
   return order;
}

static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) {
   if (!(element instanceof Class)) {
      return findOrder(annotations);
   }
   Object cached = orderCache.get(element);
   if (cached != null) {
      return (cached instanceof Integer ? (Integer) cached : null);
   }
   Integer result = findOrder(annotations);
   orderCache.put(element, result != null ? result : NOT_ANNOTATED);
   return result;
}

@Nullable
private static Integer findOrder(MergedAnnotations annotations) {
   MergedAnnotation<Order> orderAnnotation = annotations.get(Order.class);
   if (orderAnnotation.isPresent()) {
      return orderAnnotation.getInt(MergedAnnotation.VALUE);
   }
   MergedAnnotation<?> priorityAnnotation = annotations.get(JAVAX_PRIORITY_ANNOTATION);
   if (priorityAnnotation.isPresent()) {
      return priorityAnnotation.getInt(MergedAnnotation.VALUE);
   }
   return null;
}

创建代理

获取到可用的Advisor后,便可以使用它们配置代理。spring使用的代理共两种,jdk接口代理以及cglib类代理。

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 = new ProxyFactory();
   proxyFactory.copyFrom(this);

   // 此属性由proxy-target-class设置
   if (!proxyFactory.isProxyTargetClass()) {
      // 默认为false,除非@Configuration class被代理
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         // 设置代理接口
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }

   // 构造所有的Advisor,包含特定以及通用的,并转换为Advisor类型
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   // 增加Advisor,此处会增加declare-parents定义的接口
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   // 定制代理工厂,子类实现
   customizeProxyFactory(proxyFactory);

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

   // 获取代理对象
   return proxyFactory.getProxy(getProxyClassLoader());
}

创建代理的过程如下:

  1. 暴露目标类。这一步是提供给EventListener使用。
  2. 其实便是配置代理工厂。如果使用jdk代理,那么需要预先查找代理接口,没有合适的接口的话便改为使用类代理。
  3. 定制代理工厂,子类实现。
  4. 获取代理对象。

构造Advisors

这一步是将通用的Advisor也加入到Advisor列表中,通用的Advisor可以通过自定义自动代理构建器进行设置。例如:

<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator">
    <property name="interceptorNames" value="trace"/>
</bean>
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
   // Handle prototypes correctly...
   // 获取通用Advisor,默认为空
   Advisor[] commonInterceptors = resolveInterceptorNames();

   List<Object> allInterceptors = new ArrayList<>();
   if (specificInterceptors != null) {
      allInterceptors.addAll(Arrays.asList(specificInterceptors));
      if (commonInterceptors.length > 0) {
         if (this.applyCommonInterceptorsFirst) {
            allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
         }
         else {
            allInterceptors.addAll(Arrays.asList(commonInterceptors));
         }
      }
   }
   if (logger.isTraceEnabled()) {
      int nrOfCommonInterceptors = commonInterceptors.length;
      int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
      logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
            " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
   }

   Advisor[] advisors = new Advisor[allInterceptors.size()];
   for (int i = 0; i < allInterceptors.size(); i++) {
      // 转换为Advisor类型
      advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
   }
   return advisors;
}

private Advisor[] resolveInterceptorNames() {
   BeanFactory bf = this.beanFactory;
   ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
   List<Advisor> advisors = new ArrayList<>();
   // 可以通过自定义自动代理构建器,并通过interceptorNames属性设置
   // <property name="interceptorNames" value="..." />
   for (String beanName : this.interceptorNames) {
      if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
         Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
         Object next = bf.getBean(beanName);
         advisors.add(this.advisorAdapterRegistry.wrap(next));
      }
   }
   return advisors.toArray(new Advisor[0]);
}

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
   if (adviceObject instanceof Advisor) {
      return (Advisor) adviceObject;
   }
   if (!(adviceObject instanceof Advice)) {
      throw new UnknownAdviceTypeException(adviceObject);
   }
   Advice advice = (Advice) adviceObject;
   if (advice instanceof MethodInterceptor) {
      // So well-known it doesn't even need an adapter.
      return new DefaultPointcutAdvisor(advice);
   }
   for (AdvisorAdapter adapter : this.adapters) {
      // Check that it is supported.
      if (adapter.supportsAdvice(advice)) {
         return new DefaultPointcutAdvisor(advice);
      }
   }
   throw new UnknownAdviceTypeException(advice);
}

评估代理接口

这一步是评估beanClass实现的接口是否可以合法被jdk代理,主要是过滤spring的某些内置接口后,判断其他接口是否只是一个标记接口。如果是的话,那么将没有方法可供代理实现,因此需要使用cglib类代理。

protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
   // 获取这个beanClass的所有接口
   Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
   boolean hasReasonableProxyInterface = false;
   // 寻找是否有可以合法代理的接口
   for (Class<?> ifc : targetInterfaces) {
      // 过滤某些不可用的接口
      if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
            ifc.getMethods().length > 0) {
         hasReasonableProxyInterface = true;
         break;
      }
   }
   if (hasReasonableProxyInterface) {
      // Must allow for introductions; can't just set interfaces to the target's interfaces only.
      for (Class<?> ifc : targetInterfaces) {
         proxyFactory.addInterface(ifc);
      }
   }
   else {
      // 如果没有,则使用类代理
      proxyFactory.setProxyTargetClass(true);
   }
}

protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
   return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
         AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}

protected boolean isInternalLanguageInterface(Class<?> ifc) {
   return (ifc.getName().equals("groovy.lang.GroovyObject") ||
         ifc.getName().endsWith(".cglib.proxy.Factory") ||
         ifc.getName().endsWith(".bytebuddy.MockAccess"));
}

获取代理对象

首先创建Spring内置的aop代理对象,再通过aop代理对象获取真正的代理对象。

创建Spring内置的aop代理对象主要是判断使用jdk接口代理还是cglib代理:

  1. 自定义自动代理构建器,并设置optimize属性为true
  2. 设置proxy-target-class为true
  3. beanClass没有合理的代理接口

满足以上任意一条,并且beanClass不为接口或代理类,那么使用cglib代理;否则使用jdk代理。

public Object getProxy(@Nullable ClassLoader classLoader) {
   return createAopProxy().getProxy(classLoader);
}

protected final synchronized AopProxy createAopProxy() {
   // 只执行一次,首次调用此方法时激活
   if (!this.active) {
      activate();
   }
   return getAopProxyFactory().createAopProxy(this);
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   // 1. 自定义自动代理构建器,并设置optimize属性为true
   // 2. 设置proxy-target-class为true 
   // 3. beanClass没有合理的代理接口
   // 满足以上任意一条,并且beanClass不为接口或代理类,使用cglib代理;否则使用jdk代理
   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);
   }
}

private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
   Class<?>[] ifcs = config.getProxiedInterfaces();
   return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}

下面我们分别看一下jdk接口代理与cglib类代理的实现。

jdk接口代理

让我们进入其getProxy(ClassLoader)方法:

public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
   }
   // 补充代理接口
   Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
   // 寻找代理接口是否定义了equals和hashCode方法
   findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
   // 创建代理对象
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

首先补充代理接口。此方法会尝试加入三个Spring内置的接口SpringProxy, AdvisedDecoratingProxy,其中SpringProxy一定会被增加。另两个接口也默认增加,如果自定义自动代理构建器,并设置其opaque属性为true,那么Advised接口将不会被增加。

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
   // 获取之前查找的代理接口
   Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
   if (specifiedInterfaces.length == 0) {
      // No user-specified interfaces: check whether target class is an interface.
      Class<?> targetClass = advised.getTargetClass();
      if (targetClass != null) {
         if (targetClass.isInterface()) {
            advised.setInterfaces(targetClass);
         }
         else if (Proxy.isProxyClass(targetClass)) {
            advised.setInterfaces(targetClass.getInterfaces());
         }
         specifiedInterfaces = advised.getProxiedInterfaces();
      }
   }
   // 如果代理接口没有SpringProxy接口或其子接口,那么增加它
   boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
   // isOpaque()方法默认返回false
   boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
   boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
   int nonUserIfcCount = 0;
   if (addSpringProxy) {
      nonUserIfcCount++;
   }
   if (addAdvised) {
      nonUserIfcCount++;
   }
   if (addDecoratingProxy) {
      nonUserIfcCount++;
   }
   Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
   System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
   int index = specifiedInterfaces.length;
   if (addSpringProxy) {
      proxiedInterfaces[index] = SpringProxy.class;
      index++;
   }
   if (addAdvised) {
      proxiedInterfaces[index] = Advised.class;
      index++;
   }
   if (addDecoratingProxy) {
      proxiedInterfaces[index] = DecoratingProxy.class;
   }
   return proxiedInterfaces;
}

其中SpringProxy接口是一个标记接口,表明这个实例是一个spring代理实现。Advised接口可以在创建完代理对象后增加或者删除新的advisor或者advice,因此有一定的动态特性。DecoratingProxy的作用在多重代理时获取最底层的源对象类型。关于Advised接口的更多信息,请查看6.7. Manipulating Advised Objects

其次判断所有的代理接口是否有实现equals或者hashCode方法,如果有那么便记录下来,当以后调用代理对象的这两个方法时,将优先使用用户自己实现的方法,否则spring将会提供这两个方法的实现。

private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
   for (Class<?> proxiedInterface : proxiedInterfaces) {
      Method[] methods = proxiedInterface.getDeclaredMethods();
      for (Method method : methods) {
         if (AopUtils.isEqualsMethod(method)) {
            this.equalsDefined = true;
         }
         if (AopUtils.isHashCodeMethod(method)) {
            this.hashCodeDefined = true;
         }
         if (this.equalsDefined && this.hashCodeDefined) {
            return;
         }
      }
   }
}

最后,调用Proxy#newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法创建代理对象。

注意,JdkDynamicAopProxy对象实现了InvocationHandler接口,因此aop增强将在其invoke方法中实现。

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 {
      // 处理equals和hashCode方法
      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.
         // 处理DecoratingProxy接口定义的方法
         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...
         // 处理Advised接口定义的方法
         return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
      }

      Object retVal;

      // 如果配置expose-proxy属性为true,那么设置当前代理对象
      // 此处解释了((Pojo) AopContext.currentProxy()).bar()这类调用的原理
      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);

      // Get the interception chain for this method.
      // 获取此方法的拦截链,即各种advice
      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 {
         // We need to create a method invocation...
         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);
      }
   }
}

此方法的实现虽然比较长,但是逻辑清晰,容易理解。

  1. 处理特殊方法,例如equalshashCode,以及之前补充接口时增加的接口方法
  2. 获取此方法的拦截链,即各种advice
  3. 如果拦截链为空,那么直接反射调用此方法;否则,按拦截链执行。
  4. 修饰返回值
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
   MethodCacheKey cacheKey = new MethodCacheKey(method);
   List<Object> cached = this.methodCache.get(cacheKey);
   if (cached == null) {
      cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
            this, method, targetClass);
      this.methodCache.put(cacheKey, cached);
   }
   return cached;
}

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

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

   for (Advisor advisor : advisors) {
      // advisor和advice
      if (advisor instanceof PointcutAdvisor) {
         // Add it conditionally.
         PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
         // createProxy方法中默认设置为true
         if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
            // 判断方法是否匹配
            MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
            boolean match;
            // pointcut的表示类AspectJExpressionPointcut实现了此接口
            if (mm instanceof IntroductionAwareMethodMatcher) {
               if (hasIntroductions == null) {
                  // 如果declare-parents的type-matching能够匹配此类
                  hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
               }
               match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
            }
            else {
               match = mm.matches(method, actualClass);
            }
            if (match) {
               // 从advisor中获取拦截器
               MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
               if (mm.isRuntime()) {
                  // Creating a new object instance in the getInterceptors() method
                  // isn't a problem as we normally cache created chains.
                  for (MethodInterceptor interceptor : interceptors) {
                     interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                  }
               }
               else {
                  interceptorList.addAll(Arrays.asList(interceptors));
               }
            }
         }
      }
      // declare-parents
      else if (advisor instanceof IntroductionAdvisor) {
         IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
         if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
         }
      }
      else {
         Interceptor[] interceptors = registry.getInterceptors(advisor);
         interceptorList.addAll(Arrays.asList(interceptors));
      }
   }

   return interceptorList;
}

获取拦截器的主要逻辑还是检验advisor是否可以应用到此方法上,我们不关心pointcut表达式解析器的实现,只看拦截器的获取。

方法主体分为三个if判断,不过spring内置的Advisor实现类都是PointcutAdvisorIntroductionAdvisor的子类,分别对应使用poincutdeclare-parents

Advisor中获取的拦截器类型必须为MethodInterceptor,如果你自定义的advice没有实现此接口,只能通过适配器进行兼容。Spring提供了三种适配器MethodBeforeAdviceAdapter, AfterReturningAdviceAdapter, ThrowsAdviceAdapter,分别适配MethodBeforeAdvice, AfterReturningAdviceThrowsAdvice这三种advice。你也可以实现自己的Advice,不过必须要实现Advice接口,并且提供一个支持此Advice的适配器,即实现AdvisorAdapter接口,它是Spring提供的一个SPI。当然,你需要通过xml文件或者注解告知spring需要注册此实例,Spring会自动将它注册到GlobalAdvisorAdapterRegistry中,如下所示:

public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {

   private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();


   /**
    * Specify the AdvisorAdapterRegistry to register AdvisorAdapter beans with.
    * Default is the global AdvisorAdapterRegistry.
    * @see GlobalAdvisorAdapterRegistry
    */
   public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
      this.advisorAdapterRegistry = advisorAdapterRegistry;
   }


   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      return bean;
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      if (bean instanceof AdvisorAdapter){
         this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);
      }
      return bean;
   }

}

AdvisorAdapterRegistrationManager实现了BeanPostProcessor接口,当创建你自定义的AdvisorAdapter实例时,会注册它。

注意,获取到拦截advice后会进行缓存,因此之后再次调用此方法时性能会获得提升。

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
   List<MethodInterceptor> interceptors = new ArrayList<>(3);
   Advice advice = advisor.getAdvice();
   if (advice instanceof MethodInterceptor) {
      interceptors.add((MethodInterceptor) advice);
   }
   for (AdvisorAdapter adapter : this.adapters) {
      if (adapter.supportsAdvice(advice)) {
         interceptors.add(adapter.getInterceptor(advisor));
      }
   }
   if (interceptors.isEmpty()) {
      throw new UnknownAdviceTypeException(advisor.getAdvice());
   }
   return interceptors.toArray(new MethodInterceptor[0]);
}

Spring也提供了硬编码使用代理的方法,即使用ProxyFactory。此时可以自定义AdvisorChainFactoryAdvisorAdapterRegistry,并使用自定义的适配器。如下所示:

public class Main {
    public static void main(String[] args) {
        ProxyFactory factory = new ProxyFactory(new SerializablePerson());
        factory.addInterface(Person.class);
        factory.addAdvice(new CountingBeforeAdvice());
        factory.setExposeProxy(true);
        // 自定义AdvisorChainFactory,实现getInterceptorsAndDynamicInterceptionAdvice方法
        // 自定义AdvisorAdapterRegistry,并在getInterceptorsAndDynamicInterceptionAdvice方法中使用
        AdvisorChainFactory chainFactory = new MyAdvisorChainFactory();
        factory.setAdvisorChainFactory(chainFactory);
    }
}

class MyAdvisorChainFactory implements AdvisorChainFactory, Serializable {
    private AdvisorAdapterRegistry registry = new MyAdvisorAdapterRegistry();
    
    @NotNull
    @Override
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
            @NotNull Advised config, @NotNull Method method, Class<?> targetClass) {
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList<>(advisors.length);
        for(Advisor advisor : advisors) {
            interceptorList.add(registry.getInterceptors(advisor));
        }
        return interceptorList;
    }
}

class MyAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    private final List<AdvisorAdapter> adapters = new ArrayList<>();
    
    public MyAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    @NotNull
    @Override
    public MethodInterceptor[] getInterceptors(@NotNull Advisor advisor) throws UnknownAdviceTypeException {
        return new MethodInterceptor[0];
    }

    @NotNull
    @Override
    public Advisor wrap(@NotNull Object advice) throws UnknownAdviceTypeException {
        return null;
    }

    public void registerAdvisorAdapter(@NotNull AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }
}

获取到拦截器链后,如果拦截器链为空,那么通过反射直接调用,不过spring做了一点预处理适配参数。当调用方法拥有可变参数,并且实参类型与形参类型不同,spring会进行类型适配。

static Object[] adaptArgumentsIfNecessary(Method method, @Nullable Object[] arguments) {
   if (ObjectUtils.isEmpty(arguments)) {
      return new Object[0];
   }
   if (method.isVarArgs()) {
      if (method.getParameterCount() == arguments.length) {
         Class<?>[] paramTypes = method.getParameterTypes();
         int varargIndex = paramTypes.length - 1;
         Class<?> varargType = paramTypes[varargIndex];
         if (varargType.isArray()) {
            Object varargArray = arguments[varargIndex];
            // 实参为数组并且其类型与形参不同
            if (varargArray instanceof Object[] && !varargType.isInstance(varargArray)) {
               Object[] newArguments = new Object[arguments.length];
               System.arraycopy(arguments, 0, newArguments, 0, varargIndex);
               // 获取形参元素类型
               Class<?> targetElementType = varargType.getComponentType();
               // 获取实参数组长度
               int varargLength = Array.getLength(varargArray);
               // 构造数组,类型为形参元素类型
               Object newVarargArray = Array.newInstance(targetElementType, varargLength);
               System.arraycopy(varargArray, 0, newVarargArray, 0, varargLength);
               newArguments[varargIndex] = newVarargArray;
               return newArguments;
            }
         }
      }
   }
   return arguments;
}

如果拦截器链不为空,那么将构造ReflectiveMethodInvocation,在其中进行拦截器的执行。

protected ReflectiveMethodInvocation(
      Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
      @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

   this.proxy = proxy;
   this.target = target;
   this.targetClass = targetClass;
   this.method = BridgeMethodResolver.findBridgedMethod(method);
   this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
   this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}

public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   // 拦截器调用完成后,调用连接点,即方法本身
   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);
   }
}

此处会对InterceptorAndDynamicMethodMatcher进行特殊处理。由于某些aspectj pointcut表达式拥有动态特性,所有需要根据具体参数再次匹配是否适用此拦截器。

此处,我们分析最常用的五种advice:before, after, after-returning, after-throwingaround

首先是before advice对应的MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

    private final MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }


    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }

}

public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
   invokeAdviceMethod(getJoinPointMatch(), null, null);
}

protected Object invokeAdviceMethod(
      @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
      throws Throwable {

   // 进行参数绑定,然后调用advice方法
   return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
   Object[] actualArgs = args;
   if (this.aspectJAdviceMethod.getParameterCount() == 0) {
      actualArgs = null;
   }
   try {
      ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
      // TODO AopUtils.invokeJoinpointUsingReflection
      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();
   }
}

MethodBeforeAdviceInterceptor的调用便是先调用与之关联的advice方法,然后再调用mi.proceed()回到调用链。

after对应的拦截器为AspectJAfterAdvice:

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

先继续调用链,调用链执行完成后再调用其advice方法。

after-returning对应的拦截器为AfterReturningAdviceInterceptor:

public Object invoke(MethodInvocation mi) throws Throwable {
   Object retVal = mi.proceed();
   this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
   return retVal;
}

也是先继续调用链,调用链执行完成后获取其返回值,然后调用其advice方法。

after-throwing对应的拦截器为AspectJAfterThrowingAdvice:

public Object invoke(MethodInvocation mi) throws Throwable {
   try {
      return mi.proceed();
   }
   catch (Throwable ex) {
      if (shouldInvokeOnThrowing(ex)) {
         invokeAdviceMethod(getJoinPointMatch(), null, ex);
      }
      throw ex;
   }
}

around对应的拦截器为AspectJAroundAdvice:

public Object invoke(MethodInvocation mi) throws Throwable {
   if (!(mi instanceof ProxyMethodInvocation)) {
      throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
   }
   ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
   ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
   JoinPointMatch jpm = getJoinPointMatch(pmi);
   return invokeAdviceMethod(pjp, jpm, null, null);
}

它们具体的执行顺序与配置文件中的定义顺序相关。

拦截链执行完成后,spring会对返回值进行修饰。当方法的返回值为this,并且这个方法的返回类型是类型兼容的,并且这个bean没有实现RawTargetAccess接口,那么spring会帮助把这个this替换为代理对象。

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

至此,jdk接口代理的实现分析完毕。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容