专栏首页java 成神之路spring 之 import标签、alias标签、beans标签 解析

spring 之 import标签、alias标签、beans标签 解析

继续接着Spring 加载、解析applicationContext.xml 流程解析 import 、 alias、beans 标签。

DefaultBeanDefinitionDocumentReader.parseDefaultElement()

1. import 标签解析

标签示例

<import resource="user-appalicationContext.xml"/>

解析import 标签

入口类、方法DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource();

protected void importBeanDefinitionResource(Element ele) {
    // 解析 resource 属性
    String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
    //如果为空,不做处理
    if (!StringUtils.hasText(location)) {
        getReaderContext().error("Resource location must not be empty", ele);
        return;
    }

    // 解析系统属性。比如 "${user.dir}"
    location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

    Set<Resource> actualResources = new LinkedHashSet<>(4);

    boolean absoluteLocation = false;
    try {
        // 判断 location 是绝对路径还是相对路径
        absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
    }catch (URISyntaxException ex) {
        // cannot convert to an URI, considering the location relative
        // unless it is the well-known Spring prefix "classpath*:"
    }
    // 绝对路径
    if (absoluteLocation) {
        try {
            //加载xml配置文件,并解析资源
            int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
            }
        }catch (BeanDefinitionStoreException ex) {
            getReaderContext().error(
                    "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
        }
    }else {
        // No URL -> considering resource location as relative to the current file.
        try {
            int importCount;
            //获取绝对路径,并解析文件
            Resource relativeResource = getReaderContext().getResource().createRelative(location);
            if (relativeResource.exists()) {
                //加载xml文件,并解析
                importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
                actualResources.add(relativeResource);
            }else {
                // 获取URL 路径,并解析文件
                String baseLocation = getReaderContext().getResource().getURL().toString();
                importCount = getReaderContext().getReader().loadBeanDefinitions(
                        StringUtils.applyRelativePath(baseLocation, location), actualResources);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
            }
        }
        catch (IOException ex) {
            getReaderContext().error("Failed to resolve current resource location", ele, ex);
        }catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
                ele, ex);
        }
    }
    Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
    getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
  1. 获取resource属性
  2. 解析路径中的系统属性,格式如“${user.dir}”
  3. 判断location是绝对路径还是相对路径
  4. 如果是绝对路径,则递归调用bean的解析过程。重新执行这个流程 Spring 加载、解析applicationContext.xml 流程
  5. 如果相对路径,则把相对路径转换成绝对路径,在解析
  6. 通过监听器、解析完成

2. alias 标签解析

alias 标签示例

<bean id="user" class="cn.com.infcn.test.User"></bean>
<alias name="user" alias="myUser" />

解析 alias 标签

DefaultBeanDefinitionDocumentReader.processAliasRegistration()

protected void processAliasRegistration(Element ele) {
    //获取 name属性
    String name = ele.getAttribute(NAME_ATTRIBUTE);
    //获取 alias 属性
    String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
    boolean valid = true;
    //验证 name 是否为空
    if (!StringUtils.hasText(name)) {
        getReaderContext().error("Name must not be empty", ele);
        valid = false;
    }
    //验证 alias 是否为空
    if (!StringUtils.hasText(alias)) {
        getReaderContext().error("Alias must not be empty", ele);
        valid = false;
    }
    if (valid) {
        try {
            //把 alias 注册到 SimpleAliasRegistry.aliasMap 中
            getReaderContext().getRegistry().registerAlias(name, alias);
        }
        catch (Exception ex) {
            getReaderContext().error("Failed to register alias '" + alias +
                    "' for bean with name '" + name + "'", ele, ex);
        }
        getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
    }
}
  1. 解析 alias 标签,获取 name 和 alias 属性值。
  2. 把 name 和 alias 注册到 SimpleAliasRegistry.aliasMap 属性中。

SimpleAliasRegistry 源码

public class SimpleAliasRegistry implements AliasRegistry {

    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

    @Override
    public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        if (alias.equals(name)) {
            this.aliasMap.remove(alias);
        }else {
            String registeredName = this.aliasMap.get(alias);
            if (registeredName != null) {
                if (registeredName.equals(name)) {
                    // An existing alias - no need to re-register
                    return;
                }
                if (!allowAliasOverriding()) {
                    throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                            name + "': It is already registered for name '" + registeredName + "'.");
                }
            }
            checkForAliasCircle(name, alias);
            this.aliasMap.put(alias, name);
        }
    }

    protected boolean allowAliasOverriding() {
        return true;
    }
    ......

3. beans 标签解析

beans标签示例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <bean id="user" class="cn.com.infcn.test.User"></bean>
    <beans>
        ......
    </beans>
</beans>

beans 标签解析 又调用了doRegisterBeanDefinitions() 方法,这个方法在Spring 加载、解析applicationContext.xml 流程中已经介绍过了。 跟import 解析都类似。又相当于重新执行解析了一边 bean 标签一样。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java 中的内省 introspector

    java404
  • java.util.Random 实现原理

    java404
  • MTU 和 MSS 区别

    java404
  • C#多播委托(Multicast Delegate)

    委托可以包含多个方法,这种委托称为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名必须返回void,否则就只能得到委托调用的最后一个方...

    卡尔曼和玻尔兹曼谁曼
  • Asp.Net Core NLog 将日志输出到数据库以及添加LayoutRenderer的支持

    在这之前打算用Apache的Log4Net,但是发现其AdoNetAppender方法已经不存在了,无法使用配置文件直接输出到数据库了,因此我便改用了NL...

    HueiFeng
  • oracle数据库 如何查询某个表的约束条件

    使用下面语句从all_constraints视图中查看某表上的约束: SELECT constraint_name, table_name, r_owner...

    cloudskyme
  • 【笔记4-商品模块】从0开始 独立完成企业级Java电商网站开发(服务端)

    1.parent_id是因为分类采用树状分类,递归需要边界条件。2.父类别id=0时,说明是根节点,一级类别,此时为return条件。3.status可选为1或...

    chenchenchen
  • 「走进k8s」Kubernetes1.15.1的部署 Wordpress(29)

    PS:各位老铁下去仔细看下yaml的编写 和添加下 自动扩缩容,主要wordpress提高应用稳定性的方式和方法,这都是前面学习过的,等于把前面一起学习的回顾下...

    IT故事会
  • Zmap详细用户手册和DDOS的可行性

    0x00 背景 Zmap是美国密歇根大学研究者开发出一款工具。在第22届USENIX安全研讨会,以超过nmap 1300倍的扫描速度声名鹊起。相比大名鼎鼎的nm...

    小小科
  • 图论加法

    在读到这个标题的时候,小伙伴是不是会觉得很疑惑,为什么图论能有加法?难道两个图可以加在一起?两个点可以加在一起? 在原来的数学范围是做不到的,但是如果是定义了一...

    林德熙

扫码关注云+社区

领取腾讯云代金券