Spring Aop的解析

80 阅读3分钟

1. 标签的解析

因为在spring 的配置中,默认解析的标签只有 bean beans import alias 这四种,所以了解aop实现的第一步,就需要先从 aop标签的解析

关于bean 的解析,在 DefaultBeanDefinitionDocumentReader.java

 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 ele) {
           if (delegate.isDefaultNamespace(ele)) {
             // 默认的 bean、beans、alias、import 的解析
             parseDefaultElement(ele, delegate);
           }
           else {
             // 通过 一个BeanDefinition的Parser 代理解析第三方的标签
             delegate.parseCustomElement(ele);
           }
         }
       }
     }
     else {
       delegate.parseCustomElement(root);
     }
   }
 ​
   private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
     // import 标签
     if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
       importBeanDefinitionResource(ele);
     }
     // alias 标签
     else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
       processAliasRegistration(ele);
     }
     // bean 标签
     else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
       processBeanDefinition(ele, delegate);
     }
     // beans 标签
     else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
       // recurse
       doRegisterBeanDefinitions(ele);
     }
   }

1.1 找到 namespaceUri

当我们点进去 BeanDefinitionParserDelegate.java 中的 delegate.parseCustomElement(root) 这一句的实现时

   public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
     // 先找到标签对应的 namespaceUri 命名空间
     String namespaceUri = getNamespaceURI(ele);
     if (namespaceUri == null) {
       return null;
     }
     // 根据 命名空间找到对应的 NamespaceHandler
     NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
     if (handler == null) {
       error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
       return null;
     }
     // 根据自定义的 NamespaceHanlder 进行解析
     return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
   }

getNamespaceURI(ele) 中,是通过获取 node.getNamespaceURI(); aop 的就是 http://www.springframework.org/schema/aop

1.2 通过 namespaceUri 找到对应的 NamespaceHandler。

看 DefaultNamespaceHandlerResolver.java 中的 resolve 方法

     public NamespaceHandler resolve(String namespaceUri) {
       // 获取所有已经配置的 handler 映射
         Map<String, Object> handlerMappings = this.getHandlerMappings();
       // 根据命名空间找到对应的信息,这里是 handler Or className 两种状态
         Object handlerOrClassName = handlerMappings.get(namespaceUri);
         if (handlerOrClassName == null) {
             return null;
         } else if (handlerOrClassName instanceof NamespaceHandler) {
           // 如果已经解析完成,从缓存中获取
             return (NamespaceHandler)handlerOrClassName;
         } else {
           // 如果没有解析,返回的是类路径
             String className = (String)handlerOrClassName;
 ​
             try {
               // className 转化成 class
                 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");
                 } else {
                   // 初始化类
                     NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
                   // 调用 init() 方法
                     namespaceHandler.init();
                   // 放到缓存map里面
                     handlerMappings.put(namespaceUri, namespaceHandler);
                     return namespaceHandler;
                 }
             } catch (ClassNotFoundException var7) {
                 throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", var7);
             } catch (LinkageError var8) {
                 throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", var8);
             }
         }
     }

通过debug,可以看到 handlerMappings 里面的内容

image-20220802151243950.png

可以看到 aop 的解析具体实现是通过org.springframework.aop.config.AopNamespaceHandler 实现的。

1.3 执行handler.parse

在获取到 NamespaceHandler 之后,spring就将解析工作委托给 自定义解析去取解析了

来到 NamespaceHandlerSupport.java 是一个 abstract 抽象类。

   @Override
   @Nullable
   public BeanDefinition parse(Element element, ParserContext parserContext) {
     // 寻找到解析器
     BeanDefinitionParser parser = findParserForElement(element, parserContext);
     // 执行解析操作
     return (parser != null ? parser.parse(element, parserContext) : null);
   }

1.3.1 寻找解析器

 @Nullable
   private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
     // 获取元素名称,例如 aspectj-autoproxy 之类的
     String localName = parserContext.getDelegate().getLocalName(element);
     // 找到对应的 解析器
     BeanDefinitionParser parser = this.parsers.get(localName);
     if (parser == null) {
       parserContext.getReaderContext().fatal(
           "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
     }
     return parser;
   }

image-20220802155519032.png

1.3.2 执行解析

parser.parse(element, parserContext)

2. 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.5+ XSDs
     registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
     registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
     registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
 ​
     // Only in 2.0 XSD: moved to context namespace in 2.5+
     registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
   }
 ​
 }
 ​

通过上一步我们知道,当遇到 aspectj-autoproxy 标签的时候,会调用 AspectJAutoProxyBeanDefinitionParser 进行解析,接下来的全部以 aspectj-autoproxy 为例。

2.1 关于 AspectJAutoProxyBeanDefinitionParser

 class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
 ​
   @Override
   @Nullable
   public BeanDefinition parse(Element element, ParserContext parserContext) {
     // 注册 AnnotationAwareAspectJAutoProxyCreator
     AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
     // 对于注解中的子类处理
     extendBeanDefinition(element, parserContext);
     return null;
   }
 }

其中的AopNamespaceUtils 中的静态方法registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element) 是我们比较关心的。

 // 注册 AnnotationAutoProxyCreator
 public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
     ParserContext parserContext, Element sourceElement) {
 // 注册或升级 beanName是 org.springframework.aop.config.internalAutoProxyCreator 的BeanDefinition
   BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
       parserContext.getRegistry(), parserContext.extractSource(sourceElement));
   // 处理 proxy-target-class 和 expose-proxy 属性
   useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
   // 注册组件并且通知,以便监听器做进一步处理
   registerComponentIfNecessary(beanDefinition, parserContext);
 }
 ​
 private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
   if (sourceElement != null) {
     // proxy-target-class tags
     boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
     if (proxyTargetClass) {
       AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
     }
     // expose-proxy tags
     boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
     if (exposeProxy) {
       AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
     }
   }
 }
 ​
 private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
   if (beanDefinition != null) {
     // 注册组件
     parserContext.registerComponent(
         new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
   }
 }

其中的重点是 registerAspectJAnnotationAutoProxyCreatorIfNecessary

   @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);
     // 注册到 beanFactory
     registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
     return beanDefinition;
   }

2.2 关于 AnnotationAwareAspectJAutoProxyCreator

他可以根据 @Ponit 注解定义的切点来自动代理相匹配的bean。

image-20220802165046091.png

可以看到 他还实现了 BeanPostPorcessor 接口,在实现 BeanPostPorcessor 接口之后,当Spring 加载这个Bean的时候会在实例化前调用postProcessAfterInitialization