自定义标签

177 阅读2分钟
  • 解析标签开始
    • 内置标签:import、alias、bean、beans
    • 自定义标签:context:property-placeholder
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   //默认的命名空间,spring中默认的标签。
   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 {
               //解析自定标签。
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
      delegate.parseCustomElement(root);
   }
}

parseCustomElement:

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

命名空间解析过程

获取标签名的命名空间,例如

context:property-placeholder:context="http://www.springframework.org/schema/context

获取到对应标签的链接地址,有网络的情况下会下载,在没有网络的情况下回从本地加载,例如:在spring-bean项目中的spring-context/src/main/resources/META-INF下的spring.handlers中

http://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

定义了对应标签的解析类,会把org.springframework.context.config.ContextNamespaceHandler解析类获取到。 ContextNamespaceHandler:定义了多个标签的解析类。

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
   @Override
   public void init() {
      registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
      registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
      registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
      registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
      registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
   }
}

解析类加载过程

createReaderContext(resource),会创建命名空间解析器。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   // 对xml的beanDefinition进行解析,创建解析对象。
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   //beanFactory
   int countBefore = getRegistry().getBeanDefinitionCount();
   // #完成具体的解析过程,实际做解析的工作。
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   return getRegistry().getBeanDefinitionCount() - countBefore;
}

new getNamespaceHandlerResolver();

public XmlReaderContext createReaderContext(Resource resource) {
   return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
         this.sourceExtractor, this, getNamespaceHandlerResolver());
}

getNamespaceHandlerResolver()

public NamespaceHandlerResolver getNamespaceHandlerResolver() {
   if (this.namespaceHandlerResolver == null) {
      this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
   }
   return this.namespaceHandlerResolver;
}

createDefaultNamespaceHandlerResolver()

protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
   ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
   return new DefaultNamespaceHandlerResolver(cl);
}

DefaultNamespaceHandlerResolver()
** DEFAULT_HANDLER_MAPPINGS_LOCATION:META-INF/spring.handlers***

public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) {
   this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
}

DefaultNamespaceHandlerResolver中的getHandlerMappings会加载对饮的属性值变成key-value形式,例
key:www.springframework.org/schema/bean… valye:org.springframework.context.config.ContextNamespaceHandler

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 {
               // this.handlerMappingsLocation在构造函数中已经被初始化为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());
               // 将properties格式文件合并到map格式的handlerMapping中
               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;
}

调用NamespaceHandlerResolverder的resolver方法
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 通过 key获取到对应的value(全限定类名)并实例化解析对象,调用自定义的namespaceHandler的初始化方法

@Override
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
   // 获取所有已经配置好的handler映射
   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的初始化方法。
         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);
      }
   }
}

调用自定义的namespaceHandler的初始化方法 init方法。

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
   @Override
   public void init() {
      registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
      registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
      registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
      registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
      registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
   }
}

抽象类的NamespaceHandlerSupport.registerBeanDefinitionParser定义了map

private final Map<String, BeanDefinitionParser> parsers = new HashMap<>();
protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
   this.parsers.put(elementName, parser);
}

resoler方法中间对应的handlerMappings对象中。 key:链接 value:解析器对象

handlerMappings.put(namespaceUri, namespaceHandler);

标签的解析过程

根据命名空间找到对应的NamespaceHandlerspring

handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
   // 获取元素的解析器
   BeanDefinitionParser parser = findParserForElement(element, parserContext);
   return (parser != null ? parser.parse(element, parserContext) : null);
}

获取元素解析器

private final Map<String, BeanDefinitionParser> parsers = new HashMap<>();
    key:context
    value:
@Nullable
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
   // 获取元素名称
   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;
}

开始解析

BeanDefinitionParser.parse()
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
   // 获取元素的解析器
   BeanDefinitionParser parser = findParserForElement(element, parserContext);
   return (parser != null ? parser.parse(element, parserContext) : null);
}

AbstractBeanDefinitionParser:实际调用

@Override
@Nullable
public final BeanDefinition parse(Element element, ParserContext parserContext) {
   AbstractBeanDefinition definition = parseInternal(element, parserContext);
   if (definition != null && !parserContext.isNested()) {
      try {
         String id = resolveId(element, definition, parserContext);
         if (!StringUtils.hasText(id)) {
            parserContext.getReaderContext().error(
                  "Id is required for element '" + parserContext.getDelegate().getLocalName(element)
                        + "' when used as a top-level tag", element);
         }
         String[] aliases = null;
         if (shouldParseNameAsAliases()) {
            String name = element.getAttribute(NAME_ATTRIBUTE);
            if (StringUtils.hasLength(name)) {
               aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
            }
         }
         // 将AbstractBeanDefinition转换为BeanDefinitionHolder并注册
         BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
         registerBeanDefinition(holder, parserContext.getRegistry());
         if (shouldFireEvents()) {
            // 通知监听器进行处理
            BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
            postProcessComponentDefinition(componentDefinition);
            parserContext.registerComponent(componentDefinition);
         }
      }
      catch (BeanDefinitionStoreException ex) {
         String msg = ex.getMessage();
         parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
         return null;
      }
   }
   return definition;
}

获取AbstractBeanDefinition

@Override
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
   BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
   String parentName = getParentName(element);
   if (parentName != null) {
      builder.getRawBeanDefinition().setParentName(parentName);
   }
   // 获取自定义标签中的class,此时会调用自定义解析器
   Class<?> beanClass = getBeanClass(element);
   if (beanClass != null) {
      builder.getRawBeanDefinition().setBeanClass(beanClass);
   }
   else {
      // 若子类没有重写getBeanClass方法则尝试检查子类是否重写getBeanClassName方法
      String beanClassName = getBeanClassName(element);
      if (beanClassName != null) {
         builder.getRawBeanDefinition().setBeanClassName(beanClassName);
      }
   }
   // 调用子类重写的doParse方法进行解析
   doParse(element, parserContext, builder);
   return builder.getBeanDefinition();
}

开始解析doParse

从element中获取到值然后放到buidr对象中,从而构建BeanDefinition。

@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
   super.doParse(element, parserContext, builder);

   builder.addPropertyValue("ignoreUnresolvablePlaceholders",
         Boolean.valueOf(element.getAttribute("ignore-unresolvable")));

   String systemPropertiesModeName = element.getAttribute(SYSTEM_PROPERTIES_MODE_ATTRIBUTE);
   if (StringUtils.hasLength(systemPropertiesModeName) &&
         !systemPropertiesModeName.equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) {
      builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_" + systemPropertiesModeName);
   }

   if (element.hasAttribute("value-separator")) {
      builder.addPropertyValue("valueSeparator", element.getAttribute("value-separator"));
   }
   if (element.hasAttribute("trim-values")) {
      builder.addPropertyValue("trimValues", element.getAttribute("trim-values"));
   }
   if (element.hasAttribute("null-value")) {
      builder.addPropertyValue("nullValue", element.getAttribute("null-value"));
   }
}

注册Be anDefinition

registerBeanDefinition(holder, parserContext.getRegistry());

DefaultListableBeanFactory(spring上下文)的registerBeanDefinition方法。

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {
// 注册beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 记录beanName
this.beanDefinitionNames.add(beanName);
}

自定义标签

1.多穿件一个对应的解析器处理类。在init方法中添加parse类。
2.创建一个普通的spring.handlers配置文件,让应用程序能够加载工作。
3.创建对对应标签的parser类。