前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring 之 import标签、alias标签、beans标签 解析

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

作者头像
java404
发布2018-05-18 14:17:29
2.4K0
发布2018-05-18 14:17:29
举报
文章被收录于专栏:java 成神之路

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

DefaultBeanDefinitionDocumentReader.parseDefaultElement()

1. import 标签解析

标签示例
代码语言:javascript
复制
<import resource="user-appalicationContext.xml"/>
解析import 标签

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

代码语言:javascript
复制
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 标签示例
代码语言:javascript
复制
<bean id="user" class="cn.com.infcn.test.User"></bean>
<alias name="user" alias="myUser" />
解析 alias 标签

DefaultBeanDefinitionDocumentReader.processAliasRegistration()

代码语言:javascript
复制
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 源码
代码语言:javascript
复制
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标签示例
代码语言:javascript
复制
<?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 标签一样。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.09.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. import 标签解析
    • 标签示例
      • 解析import 标签
      • 2. alias 标签解析
        • alias 标签示例
          • 解析 alias 标签
            • SimpleAliasRegistry 源码
            • 3. beans 标签解析
              • beans标签示例
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档