前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring源码分析(二)Spring怎么扩展解析xml接口的

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

作者头像
石臻臻的杂货铺[同名公众号]
发布2021-07-14 09:58:52
2620
发布2021-07-14 09:58:52
举报
文章被收录于专栏:kafka专栏

自定义Spring配置

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

BeanDefinitionParserDelegate


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

代码语言:javascript
复制
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  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  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  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
        //  as of 3.0. Therefore, no nested  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; 默认的 命名空间解析对象选择器; 主要作用就是 根据不同的命名空间来选择对应的解析器;

代码语言:javascript
复制
    /**
     * 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 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 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 handlerMappings = new ConcurrentHashMap(mappings.size());
                        CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
                        this.handlerMappings = handlerMappings;
                    }
                    catch (IOException ex) {
                        throw new IllegalStateException(
                                "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
                    }
                }
            }
        }
        return this.handlerMappings;
    }

NamespaceHandlerSupport 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 中

代码语言:javascript
复制
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;
    }


}
代码语言:javascript
复制
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());
    }

}

BeanDefinitionParser


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

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

ParserContext


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

代码语言:javascript
复制
    public ParserContext(XmlReaderContext readerContext, BeanDefinitionParserDelegate delegate,
            BeanDefinition containingBeanDefinition) {

        this.readerContext = readerContext;
        this.delegate = delegate;
        this.containingBeanDefinition = containingBeanDefinition;
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/05/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义Spring配置
  • BeanDefinitionParserDelegate
    • DefaultNamespaceHandlerResolver
    • NamespaceHandlerSupport implements NamespaceHandler
    • BeanDefinitionParser
    • ParserContext
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档