spring5.x自定义标签学习之解析原理

引言:在上一篇了解到spring的自定义标签的创建过程,接下下来我们看看自定义标签的解析原理。有不对的地方请大佬留言指出哈。

1、解析源入口:org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
	           .....
            }
        } else {
        	//自定义标签解析入口
            delegate.parseCustomElement(root);
        }
    }

2、进入parseCustomElement方法内部

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

 public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
 		//1、获取命名空间url, 获取namespaceUri= http://www.spring.test.com/shema/user
        String namespaceUri = this.getNamespaceURI(ele);
        if (namespaceUri == null) {
            return null;
        } else {
        	//2、根据命名空间url实例化自定义handler处理器
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler == null) {
                this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
                return null;
            } else {
               //3、handler进行bean加载注册
                return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
            }
        }
    }

以上主要三个方法:
2.1、String namespaceUri = this.getNamespaceURI(ele);

2.2、标签处理器 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);

public NamespaceHandler resolve(String namespaceUri) {
		//Map<‘namespace’, 'classNamePath'>,获取缓存中的handlerMappings
        Map<String, Object> handlerMappings = this.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 {
            	//用className进行反射获取handler
                Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
                if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                 .....
                } else {
                    NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
                    //调用init方法实例化handler
                    namespaceHandler.init();
                    handlerMappings.put(namespaceUri, namespaceHandler);
                    return namespaceHandler;
                }
            } catch (ClassNotFoundException var7) {
               ......
        }
    }

2.2.1、获取缓存中的handlerMappings , this.getHandlerMappings()方法

org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings
此DefaultNamespaceHandlerResolver的构造方法是进行加载找到目标"META-INF/spring.handlers",因此我们可以自定义多个handler

private Map<String, Object> getHandlerMappings() {
        Map<String, Object> handlerMappings = this.handlerMappings;
        if (handlerMappings == null) {
            synchronized(this) {
                handlerMappings = this.handlerMappings;
                if (handlerMappings == null) {
                    .....
                    try {
                    	//PropertiesLoaderUti同样进行"META-INF/spring.handlers"下的handler解析
                        Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
                        if (this.logger.isTraceEnabled()) {
                            this.logger.trace("Loaded NamespaceHandler mappings: " + mappings);
                        }

                        handlerMappings = new ConcurrentHashMap(mappings.size());
                        //handlerMappings 合并
                        CollectionUtils.mergePropertiesIntoMap(mappings, (Map)handlerMappings);
                        this.handlerMappings = (Map)handlerMappings;
                    } catch (IOException var5) {
                        throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", var5);
                    }
                }
            }
        }

        return (Map)handlerMappings;
    }

2.3、handler标签解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
2.3.1
org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse

    public BeanDefinition parse(Element element, ParserContext parserContext) {
        BeanDefinitionParser parser = this.findParserForElement(element, parserContext);
        return parser != null ? parser.parse(element, parserContext) : null;
    }

    private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
        String localName = parserContext.getDelegate().getLocalName(element);
        BeanDefinitionParser parser = (BeanDefinitionParser)this.parsers.get(localName);
        if (parser == null) {
            parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
        }

        return parser;
    }

2.3.2 最终进入默认标签解析逻辑

org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse
org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse#parseInternal

真正实现自定义的标签解析AbstractSingleBeanDefinitionParser#parseInternal

 protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
        //获取构建器
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        String parentName = this.getParentName(element);
        if (parentName != null) {
            builder.getRawBeanDefinition().setParentName(parentName);
        }

        //获取bean的class对象
        Class<?> beanClass = this.getBeanClass(element);
        if (beanClass != null) {
            builder.getRawBeanDefinition().setBeanClass(beanClass);
        } else {
        	//自定义解析器是若重写getBeanClassName,则会进行获取beanClassName
            String beanClassName = this.getBeanClassName(element);
            if (beanClassName != null) {
                builder.getRawBeanDefinition().setBeanClassName(beanClassName);
            }
        }
		//构建bean资源
        builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
        BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
        if (containingBd != null) {
        	//父类资源scope属性
            builder.setScope(containingBd.getScope());
        }
			//懒加载
        if (parserContext.isDefaultLazyInit()) {
            builder.setLazyInit(true);
        }
		//调用自定义解析器重写的doParse方法进行解析
        this.doParse(element, parserContext, builder);
        return builder.getBeanDefinition();
    }

3、BeanDefinitionParser解析器接口的实现类,可以看出spring生态的其他解析器,如:mongo、dubbo、redis等

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值