首页 > 其他分享 >spring中默认标签alias、import标签解析

spring中默认标签alias、import标签解析

时间:2023-06-05 16:13:51浏览次数:53  
标签:标签 ele alias bean location spring getReaderContext 解析

1、Alias标签

在bean标签里边有一个alias属性和name属性,可以指定bean的别名,但是有的场景下,在定义bean的时候就把他的别名都指定好是不适用的。
比如这个Bean在组件A中,想把他叫做componentA,但是在组件B中又想把他叫做componetB,所以还有一个单独的标签:< alias>专门解决上述场景的。

<bean id="myBean" class="com.itpluto.MyBean"></bean>
<alias name="myBean" alias="componetA">
<alias name="myBean" alias="componetB">

这样一来,每个组件及程序就可以通过唯一名字来引用同一个数据源而互不干扰。

Spring对alias的解析

protected void processAliasRegistration(Element ele) {
    String name = ele.getAttribute(NAME_ATTRIBUTE);
    String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
    boolean valid = true;
    if (!StringUtils.hasText(name)) {
        getReaderContext().error("Name must not be empty", ele);
        valid = false;
    }
    if (!StringUtils.hasText(alias)) {
        getReaderContext().error("Alias must not be empty", ele);
        valid = false;
    }
    // 上面两个判断可以知道,alias标签必须包含两个属性:name、alias
    if (valid) {
        try {
            // 注册别名
            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));
    }
}

其实和之前bean中的alias解析一样,都是把别名与beanName组成一对注册到register中。

 

2、Import标签

import的使用场景主要是因为项目比较大,配置文件非常多的时候,会进行分模块,这个时候就可以用到import这个标签了。

<import resource="customerContext.xml" />
<import resource="systemContext.xml" />

这样以后有新的模块加入,就可以简单修改这个文件了,这样大大简化了配置后期维护的复杂度,并且易于管理。

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;
    }

    // Resolve system properties: e.g. "${user.dir}"
    // 把resource属性的值进行处理,如果有占位符的,需要进行替换
    location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

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

    // Discover whether the location is an absolute or relative URI
    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*:"
    }

    // Absolute or relative?
    if (absoluteLocation) {
        try {
            // 绝对路径直接解析,并且加载beanDefinition即可
            int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
            if (logger.isTraceEnabled()) {
                logger.trace("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 {
        // 相对路径则根据相对地址计算绝对地址	
        try {
            int importCount;
            // Resource之前分析过有很多子类实现,比如FileSystemResource、ClassPathResource等,
            // 每个resource的createRelative方式实现都不一样,所以先使用子类的方法尝试解析
            Resource relativeResource = getReaderContext().getResource().createRelative(location);
            if (relativeResource.exists()) {
                // 解析成功则直接使用
                importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
                actualResources.add(relativeResource);
            }
            else {
                // 解析不成功,则使用默认的解析器ResourcePatternResolver进行解析
                String baseLocation = getReaderContext().getResource().getURL().toString();
                importCount = getReaderContext().getReader().loadBeanDefinitions(
                    StringUtils.applyRelativePath(baseLocation, location), actualResources);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("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[0]);
    getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}

总结一下:
1、获取resource属性的值。
2、解析路径中的系统属性,比如:${user.dir}。
3、根据resource的值来判断是绝对路径还是相对路径,如果是绝对路径直接加载解析文件即可,如果是相对路径要先计算出绝对路径。
4、通知监听器,解析完成。

标签:标签,ele,alias,bean,location,spring,getReaderContext,解析
From: https://www.cnblogs.com/blogzero/p/17458039.html

相关文章

  • 使用powermock写springboot2.7业务类的测试用例
    1,引入powermock依赖<dependency><groupId>org.powermock</groupId><artifactId>powermock-core</artifactId><version>2.0.9</version><scope>test</......
  • 【SpringBoot】如何配置静态资源的地址与访问路径
    静态资源,例如HTML文件、JS文件,设计到的SpringBoot配置有两项,一是“spring.mvc.static-path-pattern”,一是“spring.resources.static-locations”,很多人都难以分辨它们之间的差异,所以经常出现的结果就是404错误,无法找到静态资源。1.spring.mvc.static-path-patternspring.mvc.sta......
  • springmvc架构流程
    1、 用户发送请求至前端控制器DispatcherServlet2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。4、 DispatcherServlet通过HandlerAdap......
  • 为SpringBoot Admin监控的服务端加上登录认证
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>packagecom.ciih.refineinner.config;importlombok.extern.slf4......
  • 为SpringBoot Admin加上登录认证
    依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>配置server:port:8000spring:security:user:n......
  • springmvc后端接收前端数据的四种方式
    前端登录页面代码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><h1>登录页面</h1><formaction="login.do"......
  • SpringBoot Admin的基本使用(单体应用)
    springboot项目和springbootadmin项目不建议放在一起,因为目的是为了监控,如果放在一起的话,一旦springboot挂了,springbootadmin也就一起挂了,监控就失去意义.搭建监控项目:<dependencies><dependency><groupId>org.springframework.boot</groupId>......
  • SpringBoot2.x跨域问题(CrossOrigin失效问题)
    方法一SpringBoot版本的不同,CrossOrigin失效了,正确配置如下:@CrossOrigin(originPatterns="*",allowCredentials="true",maxAge=3600)方法二如果以上方法还是不生效,最后的终极方法可以进行硬编码进行跨域设置:对需要跨域的接口,进行Response对象设置可跨域URL设置(*代表......
  • kettle web springboot mvn dockerfile
    远程构建dcokerfileFROMopenjdk:8-jdk-alpineasTEMP_BUILD_IMAGERUNset-eux&&sed-i's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g'/etc/apk/repositoriesRUNapkupdate&&\apkadd--no-cachebashcurlwget&&......
  • SpringBoot2 缓存之王caffeine
    <dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.9.0</version></dependency>顺便写了个工具类配合SpringBoot使用:packag......