4.2自定义标签解析

自定义标签的解析过程入口
DefaultBeanDefinitionDocumentReader
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    //beans下的child节点bean
    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)) {
                    //解析默认配置
                    //如:<bean id="test" class="test.TestBean" />
                    parseDefaultElement(ele, delegate);
                }
                else {
                    //解析自定义配置
                    //如:<tx:annotation-driven />
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

DefaultBeanDefinitionDocumentReader
public BeanDefinition parseCustomElement(Element ele) {
    return parseCustomElement(ele, null);
}

DefaultBeanDefinitionDocumentReader
//containingBd为父类bean,如果是对顶层元素解析应该设置为null
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    //获取对应的命名空间,具体实现就不管了
    //在4.1中,获取到的就是    http://www.shing.com/schema/user
    String namespaceUri = getNamespaceURI(ele);
    if (namespaceUri == null) {
        return null;
    }
    //根据命名空间找到对应的NamespaceHandler
    //在4.1中,这里返回的是MyNamespaceHandler的实例
    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));
}

 

4.2.1获取标签的命名空间
public String getNamespaceURI(Node node) {
   return node.getNamespaceURI();
}
使用的org.w3c.dom.Node
 
4.2.2提取自定义标签处理器handler
DefaultNamespaceHandlerResolver
public NamespaceHandler resolve(String namespaceUri) {
    //获取所有已经配置的handler映射
    Map<String, Object> handlerMappings = getHandlerMappings();
    //根据命名空间查找对应的信息
    //因为是第一次,这里获取到的是4.1中spring.handlers配置的类路径userDefinedXml.MyNamespaceHandler
    //等到执行完handlerMappings.put(namespaceUri, namespaceHandler); 以后拿到的就是实例了
    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的初始化方法
            //在4.1中,这个方法就是将我们自定义解析器put到NamespaceHandlerSupport的parsers属性中
            //后面的handler.parse方法从其中获取自定义解析器
            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);
        }
    }
}

DefaultNamespaceHandlerResolver
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在构造函数中被初始化为默认值
                        //public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "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格式的handlerMappings中
                        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;
    }
需要注意的是,DefaultNamespaceHandlerResolver构造函数中将this.handler-MappingsLocation初始化为默认值,public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
还有就是通过handler.init方法将自定义标签解析器put到NamespaceHandlerSupport的parsers属性中,在这之后的handler.parse会使用到它。
 
4.2.3标签解析
NamespaceHandlerSupport
public BeanDefinition parse(Element element, ParserContext parserContext) {
    //寻找解析器并进行解析操作
    BeanDefinitionParser parser = findParserForElement(element, parserContext);
    return (parser != null ? parser.parse(element, parserContext) : null);
}

private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    //还记得4.1中customerDefinition.xml中的<myname:user
    //对,这里的localName就是user
    String localName = parserContext.getDelegate().getLocalName(element);
    //还记得namespaceHandler.init()吗
    BeanDefinitionParser parser = this.parsers.get(localName);
    if (parser == null) {
        parserContext.getReaderContext().fatal(
            "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    }
    return parser;
}

AbstractBeanDefinitionParser
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;
    }
    
AbstractSingleBeanDefinitionParser
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
    String parentName = getParentName(element);
    if (parentName != null) {
        builder.getRawBeanDefinition().setParentName(parentName);
    }
    //获取自定义标签中的class,此时会调用自定义解析器中的getBeanClass方法
    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);
        }
    }
    builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
    BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
    //若存在父类,则使用父类的scope属性
    if (containingBd != null) {
        // Inner bean definition must receive same scope as containing bean.
        builder.setScope(containingBd.getScope());
    }
    //配置延迟加载
    if (parserContext.isDefaultLazyInit()) {
        // Default-lazy-init applies to custom bean definitions as well.
        builder.setLazyInit(true);
    }
    //调用子类解析器重写的doParse方法进行解析
    doParse(element, parserContext, builder);
    return builder.getBeanDefinition();
}
知识重点:doParse的使用(设计模式)。





posted @ 2021-01-13 17:06  _Shing  阅读(244)  评论(0)    收藏  举报