《Spring源码深度解析》四

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

第四章:自定义标签的解析

围绕第二章末的delegate.parseCustomElement(root);展开,即如下代码

/**
 * 处理两大类Bean声明
 * 一个是默认的,如:<bean id=”test” class=”test.TestBean” />
 * 另一类就是自定义的,如:<tx :annotation-driven/>
 * @param root
 * @param delegate
 */

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {

    if (delegate.isDefaultNamespace(root)) {
        ...
    }
    else {//解析自定义标签(本章解析此行代码)
        delegate.parseCustomElement(root);
    }
}

4.1:自定义标签的使用

步骤:

《Spring源码深度解析》四


4.2:开始解析

思路:
1.根据对应的bean获取对应的命名空间
2.根据命名空间解析对应的处理器
3.根据用户自定义的处理器进行解析

@Nullable(BeanDefinitionParserDelegate)
public BeanDefinition parseCustomElement(Element ele) {
    return parseCustomElement(ele, null);
}
//containingBd为父类bean,对顶层元素的解析应设置为null
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    //4.2.1获取对应的命名空间
    String namespaceUri = getNamespaceURI(ele);
    if (namespaceUri == null) {
        return null;
    }
    //4.2.2根据命名空间找到对应的处理器
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    //4.2.3调用自定义的处理器进行解析
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

接下来逐步解析

4.2.1:根据对应的bean获取对应的命名空间(获取标签的命名空间)

@Nullable
public String getNamespaceURI(Node node) {
    return node.getNamespaceURI();//由org.w3c.dom.Node提供
}

4.2.2:根据命名空间解析对应的处理器(提取自定义标签处理器)

@Override
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
    //获得所有已配置的handler映射(读取Spring.handlers文件并缓存在map中)
    //(命名空间:命名空间处理器  定义在Spring.handlers文件中)
    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);
            //调用自定义的处理器的初始化方法,可以用来注册自定义BeanDefinitionParser
            //可以注册多个标签解析器,使当前命名空间可以支持多种标签解析
            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);
        }
    }
}

/**
 * 读取Spring.handlers文件并缓存在map中
 * 借助工具类PropertiesLoaderUtils对属性handlerMappingsLocation进行了配置文件的读取
 * @return
 */

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在构造方法中已经被初始化为: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;
}

此时的handler已经被实例化成我们自定义的处理器并完成了初始化工作

4.2.3:根据用户自定义的处理器进行解析(标签解析)

//使用处理器父类(NamespaceHandlerSupport)的parse方法
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    //寻找解析器,并进行解析操作
    BeanDefinitionParser parser = findParserForElement(element, parserContext);
    return (parser != null ? parser.parse(element, parserContext) : null);
}

@Nullable
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    //获取元素名称,如<myname:user>的user
    String localName = parserContext.getDelegate().getLocalName(element);
    //找到对应的解析器,即开发人员注册的解析器
    //如registerBeanDefinitionParser("user", new UserBeanDefinitionParser());的UserBeanDefinitionParser
    BeanDefinitionParser parser = this.parsers.get(localName);
    if (parser == null) {
        parserContext.getReaderContext().fatal(
                "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    }
    return parser;
}

/**
 * 用来处理将解析后的AbstractBeanDefinition转化为BeanDefinitionHolder 并注册的功能,而真正
 * 去做解析的事情委托给了函数parselntenal,正是这句代码调用了我们自定义的解析函数。
 */

@Override
@Nullable
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;
}

@Override
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
    String parentName = getParentName(element);
    if (parentName != null) {
        builder.getRawBeanDefinition().setParentName(parentName);
    }
    //获取自定义标签中的class, 此时会调用自定义解析器如UserEeanDefinitionParser中的getBeanClass方法
    Class<?> beanClass = getBeanClass(element);
    if (beanClass != null) {
        builder.getRawBeanDefinition().setBeanClass(beanClass);
    }
    else {
        //若子类没有重写getBeanClassName方法则尝试检查子类是否重写getBeanClassName方法
        String beanClassName = getBeanClassName(element);
        if (beanClassName != null) {
            builder.getRawBeanDefinition().setBeanClassName(beanClassName);
        }
    }
    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方法进行解析
    doParse(element, parserContext, builder);
    return builder.getBeanDefinition();
}

protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
    doParse(element, builder);
}

protected void doParse(Element element, BeanDefinitionBuilder builder) {
}

到此为止,Spring就将bean从配置文件加载到内存中了

接下来的任务便是如何使用bean


原文始发于微信公众号(不止于Java):《Spring源码深度解析》四