Spring源码笔记(三)自定义标签

上一节说完解析默认标签,以及默认标签中的自定义标签(在默认标签中的自定义标签使用的另一种解析方式),现在解析开始的bean中自定义标签解析:

DefaultBeanDefinitionDocumentReader类的 parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) 方法中的:
    delegate.parseCustomElement(ele);

1.parseCustomElement(Element ele, BeanDefinition containingBd)

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    String namespaceUri = getNamespaceURI(ele);
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

该类的功能有:

获取命名空间:getNamespaceURI(ele);

找到对应的命名空间处理器:this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);

标签解析:handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));

resolve(namespaceUri)

这里resolve的调用使用后缀的方式调用,getNamespaceHandlerResolver()返回NamespaceHandlerResolver类的实例,NamespaceHandlerResolver是一个接口,它的实现类有DefaultNamespaceHandlerResolver,所以这里resove方法的调用者是DefaultNamespaceHandlerResolver实例;
resolve方法:

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");
                }
                NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
                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);
            }
        }
    }

具体执行有:获取Handler映射,根据namespace找到对应的信息,判断对应的handler是否加载过,如果加载过,直接从缓存中返回,如果没有,则实现反射创建对象,然后初始化对象,然后将对象记录到缓存中。

注意这里:命名空间以及命名空间处理器的对应关系是在使用自定义标签时,配置的Spring.handlers文件中;

初始化方法会去执行BeanDefinitionParser的注册,这个方法的实现需要在自定义标签前,需要自行配置;

这里的getHandlerMappings主要是读取Spring.handlers配置文件并将配置文件缓存到map中。

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

进入NamespaceHandlerSupport的parse方法:

public BeanDefinition parse(Element element, ParserContext parserContext) {   return findParserForElement(element, parserContext).parse(element, parserContext);}
findParserForElement:

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;
    }
findParserForElement返回BeanDefinitionParser实例,AbstractBeanDefinitionParser实现BeanDefinitionParser接口。

parse(element, parserContext):

public final BeanDefinition parse(Element element, ParserContext parserContext) {
        AbstractBeanDefinition definition = parseInternal(element, parserContext);
        ......
        }
        return definition;
    }

主要解析则使用parseInternal(element,parserContext);然后获取解析后的definition实例,然后获取id,别名,并进行注册。parseInternal()是BeanDefinitionParser接口定义的方法,BeanDefinitionParser的实现类是AbstractBeanDefinitionParser抽象类,而对于parseInternal具体的实现则使用继承AbstractBeanDefinitionParser的AbstractSingleBeanDefinitionParser实例。

parseInternal(element,parserContext)

protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        String parentName = getParentName(element);
        if (parentName != null) {
            builder.getRawBeanDefinition().setParentName(parentName);
        }
        Class<?> beanClass = getBeanClass(element);
        ......
        doParse(element, parserContext, builder);
        return builder.getBeanDefinition();
    }

该方法实现的功能有:获取自定义标签中的class,获取父类中的scope属性,配置延迟加载,调用子类重写doParse方法。

补充:

对于自定义标签的配置参考 https://blog.csdn.net/wkztselina/article/details/82765949 博客,详细的介绍了如何在spring中配置自定义标签。

参考《Spring源码深度解析》

如有问题,敬请指出,与君共勉

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值