写点什么

Spring 源码分析 (二)Spring 怎么扩展解析 xml 接口的

  • 2022 年 8 月 29 日
    江西
  • 本文字数:6635 字

    阅读完需:约 22 分钟

Spring源码分析(二)Spring怎么扩展解析xml接口的

作者石臻臻,CSDN 博客之星 Top5Kafka Contributornacos Contributor华为云 MVP,腾讯云 TVP,滴滴 Kafka 技术专家 KnowStreaming, 《Kafka 运维与实战宝典》电子书作者。领取《Kafka 运维与实战宝典》PDF 请联系石臻臻


KnowStreaming 是滴滴开源的Kafka运维管控平台, 有兴趣一起参与参与开发的同学,但是怕自己能力不够的同学,可以联系我,当你导师带你参与开源!

1 自定义 Spring 配置

https://blog.csdn.net/bingduanlbd/article/details/38770685

2BeanDefinitionParserDelegate


在 DefaultBeanDefinitionDocumentReader 处理 Document 元素时,将 Document 文档内元素具体解析工作委托给 BeanDefinitionParserDelegate 类来处理,默认 BeanDefinitionParserDelegate 会处理”http://www.springframework.org/schema/beans“命名空间下元素及其属性,查看源码可以看到 BeanDefinitionParserDelegate 下面定义了一堆元素和属性名称,这些元素和属性名称分别可以在类中找到处理方法

public class BeanDefinitionParserDelegate {
 public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
 public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; "; private final XmlReaderContext readerContext;
 private final DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition(); /** *初始化 default lazy-init, autowire, dependency check settings, * init-method, destroy-method and merge settings等属性值 * 并且填充到属性 DocumentDefaultsDefinition defaults; * 如果 当前Xml文件没有配置默认属性,则查父类delegate有没有设置属性;如果没有则 使用默认配置 */ protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {  String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);  if (DEFAULT_VALUE.equals(lazyInit)) {   // Potentially inherited from outer <beans> sections, otherwise falling back to false.   lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);  }  defaults.setLazyInit(lazyInit);
  String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);  if (DEFAULT_VALUE.equals(merge)) {   // Potentially inherited from outer <beans> sections, otherwise falling back to false.   merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);  }  defaults.setMerge(merge);
  String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);  if (DEFAULT_VALUE.equals(autowire)) {   // Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.   autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);  }  defaults.setAutowire(autowire);
  // Don't fall back to parentDefaults for dependency-check as it's no longer supported in  // <beans> as of 3.0. Therefore, no nested <beans> would ever need to fall back to it.  defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
  if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {   defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));  }  else if (parentDefaults != null) {   defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());  }
  if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {   defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));  }  else if (parentDefaults != null) {   defaults.setInitMethod(parentDefaults.getInitMethod());  }
  if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {   defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));  }  else if (parentDefaults != null) {   defaults.setDestroyMethod(parentDefaults.getDestroyMethod());  }
  defaults.setSource(this.readerContext.extractSource(root)); } //解析自定义元素public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {  //获取当前Element的命名空间  String namespaceUri = getNamespaceURI(ele);  //获取namespaceHandlerResolver然后根据命名空间得到具体的 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;  }  //具体的NamespaceHandler处理类去解析Element;返回 BeanDefinition 对象  return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } //返回defaults属性值 public BeanDefinitionDefaults getBeanDefinitionDefaults() {  BeanDefinitionDefaults bdd = new BeanDefinitionDefaults();  bdd.setLazyInit("TRUE".equalsIgnoreCase(this.defaults.getLazyInit()));  bdd.setDependencyCheck(this.getDependencyCheck(DEFAULT_VALUE));  bdd.setAutowireMode(this.getAutowireMode(DEFAULT_VALUE));  bdd.setInitMethodName(this.defaults.getInitMethod());  bdd.setDestroyMethodName(this.defaults.getDestroyMethod());  return bdd; }
复制代码

DefaultNamespaceHandlerResolver


DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver;默认的 命名空间解析对象选择器; 主要作用就是 根据不同的命名空间来选择对应的解析器;

 /**  * Locate the {@link NamespaceHandler} for the supplied namespace URI  * from the configured mappings.  * @param namespaceUri the relevant namespace URI  * @return the located {@link NamespaceHandler}, or {@code null} if none found  */ @Override public NamespaceHandler resolve(String namespaceUri) {  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");    }    //加载完类之后,通过反射生成具体实例对象;例如:ContextNamespaceHandler    NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);    //调用具体对象的init()方法,注册对应的解析类,例如annotation-config 对应的解析类是 AnnotationConfigBeanDefinitionParser    namespaceHandler.init();    //将实例对象覆盖 全类名路径    handlerMappings.put(namespaceUri, namespaceHandler);    return namespaceHandler;   }   catch (ClassNotFoundException ex) {    throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +      namespaceUri + "] not found", ex);   }   catch (LinkageError err) {    throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +      namespaceUri + "]: problem with handler class file or dependent class", err);   }  } }


     /**  * 第一次加载的时候 Map里面的对象 是String类型,全类名路径  */ private Map<String, Object> getHandlerMappings() {  if (this.handlerMappings == null) {   synchronized (this) {    if (this.handlerMappings == null) {      //加载META-INF/spring.handlers的所有属性      Properties mappings =        PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);      if (logger.isDebugEnabled()) {       logger.debug("Loaded NamespaceHandler mappings: " + mappings);      }      Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());      CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);      this.handlerMappings = handlerMappings;     }     catch (IOException ex) {      throw new IllegalStateException(        "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);     }    }   }  }  return this.handlerMappings; } 
复制代码

3NamespaceHandlerSupport implements NamespaceHandler


实现了 NamespaceHandler 中的 parse()和 decorate 方法,并且提供一些属性来维护 具体的解析元素的对象 BeanDefinitionParser;例如:http://www.springframework.org/schema/context 命名空间对应的操作类是 ContextNamespaceHandler;这个操作类会调用 init()方法

@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()); }
复制代码

根据不同的属性,注册不同的解析类 BeanDefinitionParser


我们以 ContextNamespaceHandler 看下, 实现类只要实现 init 方法就行了; 对应的解析类 通过 registerBeanDefinitionParser 方法,存放到 NamespaceHandlerSupport 中的 Map parsers 中


public abstract class NamespaceHandlerSupport implements NamespaceHandler {  //将元素头 与对应的解析器对应起来  protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {   this.parsers.put(elementName, parser);  }     /** *具体的NamespaceHandler处理类去解析Element;返回 BeanDefinition 对象 * BeanDefinitionParserDelegate.parseCustomElement 中 在获取到了对应的handler后,会执行handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))方法; * 例如:获取到的操作类是  ContextNamespaceHandler,调用parse的方法其实调用了NamespaceHandlerSupportde parse方法;也就是下面的  * 例如annotation-config得到的是AnnotationConfigBeanDefinitionParser实例, 再调用AnnotationConfigBeanDefinitionParser的parse方法;这样就实现了根据不同元素来解析成 Spring中的 定义Bean BeanDefinition了; */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) {  return findParserForElement(element, parserContext).parse(element, parserContext); }
 /**  * 根据元素节点的名称 获取对应的解析类实例;例如annotation-config得到的是AnnotationConfigBeanDefinitionParser实例,  */ 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; }  }
复制代码


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

复制代码

4BeanDefinitionParser


Element 元素的解析类;只有一个方法 BeanDefinition parse(Element element, ParserContext parserContext);实现类去实现这个方法就行了;

我们看到 parse 方法中传入了 ParserContext 参数;我们了解一下这个;

5ParserContext


解析类上下文;这类 hold 住了 XmlReaderContext 和 BeanDefinitionParserDelegate;可以最大限度的让用户自已去解析

 public ParserContext(XmlReaderContext readerContext, BeanDefinitionParserDelegate delegate,   BeanDefinition containingBeanDefinition) {
  this.readerContext = readerContext;  this.delegate = delegate;  this.containingBeanDefinition = containingBeanDefinition; }
复制代码


发布于: 刚刚阅读数: 3
用户头像

关注公众号: 石臻臻的杂货铺 获取最新文章 2019.09.06 加入

进高质量滴滴技术交流群,只交流技术不闲聊 加 szzdzhp001 进群 20w字《Kafka运维与实战宝典》PDF下载请关注公众号:石臻臻的杂货铺

评论

发布
暂无评论
Spring源码分析(二)Spring怎么扩展解析xml接口的_spring 源码_石臻臻的杂货铺_InfoQ写作社区