美文网首页
Spring依赖Jar包同名配置文件冲突

Spring依赖Jar包同名配置文件冲突

作者: insomniaLee | 来源:发表于2020-04-28 21:27 被阅读0次

问题描述

昨天接到了一个需求是这样的,项目A作为公有工具类项目,被项目B和项目C所依赖,同时项目C依赖项目B。A中的配置依赖于外部的properties,在B和C中均配有同名properties以启动项目A,但是在实际运行过程中,项目B和项目C加载的是同一配置文件(可能取决于B和C的加载顺序)。现在的要求是在A中能读到所有配置的配置信息(同名配置append到属性上而不是覆盖)。之前的开发中一直用的都是SpringBoot不是Spring,对使用xml配置的这种方式感到很陌生,只能硬着头皮上。

项目A的xml配置信息

A是一个spring项目,使用classpath*的方式将外部配置加载到项目中。并使用@Value(${})的方式获取Properties里面的值。

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="order" value="2018062911" />
    <property name="locations">
        <list>
            <value>classpath*:conf_default.properties</value>
            <value>classpath*:conf.properties</value>
        </list>
    </property>
</bean>

探索

有关classpath和classpath*

Spring可以通过指定classpath*:或classpath:前缀加路径的方式从classpath下加载文件。

  • classpath*:可以从多个jar文件中加载相同的文件。
  • classpath:只能加载找到的第一个文件。
    而使用classpath加载一般的优先级为:当前classes > jar包中的classes

解决方案

找遍了也没找到这种类似的解决方案,但是有个自定义加载类从而不用@Value方式而是用静态方法读取配置的代码给了我思路。经过自己验证过目前有两种解决方案:

通过Resource读取

这种方法使用

Resource[] resources=resolver.getResources("classpath*:conf.properties" );

这样的方法来将所有的conf.properties配置文件加载到项目当中。经过检验,这种方式确实可以获取到所有的配置文件。后续思路是定义一个Properties的工具类,实现Properties的懒加载,后续项目中使用配置信息的时候使用静态方法来获取,而不是使用@Value注解的方式。

自定义加载类,重写重要方法

经过单步调试发现,Properties加载类中对于需要merge的属性,有一个方法进行处理。

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    try {
        Properties mergedProps = this.mergeProperties();
        this.convertProperties(mergedProps);
        this.processProperties(beanFactory, mergedProps);
    } catch (IOException var3) {
        throw new BeanInitializationException("Could not load properties", var3);
    }
}

再经过漫长的调用链发现,最终调用对properties赋值时,Spring采用的是对value直接覆盖的做法(Properties继承自HashTable)

String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);

到这里我们的目标就很明确了,要做的有如下几点。

  • xml中自定义加载类PropertyUtil,其他不用改变
<bean class="com.zombie.a.PropertyUtil">
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="order" value="2018062911" />
    <property name="locations">
        <list merge="true">
            <value>classpath*:conf-default.properties</value>
            <value>classpath*:conf.properties</value>
        </list>
    </property>
</bean>
  • 自定义MyProperties 继承自Properties,修改赋值逻辑
    实际这一步只要改一行代码,但是很多依赖的函数我直接也一道copy到MyProperties了
put(key, get(key)==null?value:get(key)+","+value);
  • 自定义加载类中替换Properties
    我的做法是直接重写mergeProperties方法,其实也只用该一行代码,即:Properties result = new MyProperties();
protected Properties mergeProperties() throws IOException {
    Properties result = new MyProperties();
    if (this.localOverride) {
        this.loadProperties(result);
    }

    if (this.localProperties != null) {
        Properties[] var2 = this.localProperties;
        int var3 = var2.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            Properties localProp = var2[var4];
            CollectionUtils.mergePropertiesIntoMap(localProp, result);
        }
    }
    if (!this.localOverride) {
        this.loadProperties(result);
    }
    return result;
}

验证

最后做了下验证,我定义了3个conf.properties 1个conf_default.properties最终同一属性的所有值都读到了。

default,prod,aaaa,bbb

完美!收工。

相关文章

  • Spring依赖Jar包同名配置文件冲突

    问题描述 昨天接到了一个需求是这样的,项目A作为公有工具类项目,被项目B和项目C所依赖,同时项目C依赖项目B。A中...

  • Spring MVC 集成disconf读取properties

    1. Jar包导入 使用mave添加jar依赖 2.Spring 配置文件 3.编辑properties文件 pr...

  • JVM加载jar查询

    有时在一个应用中,会依赖很多的jar包,难免会出现引用不同jar包中的同名类,或者jar包冲突,这时搞清楚: JV...

  • Maven中依赖冲突解决方案

    在使用Maven中我们导入jar包坐标时会产生依赖传递,而依赖传递难免会发生jar包间的依赖冲突,解决jar包冲突...

  • 缓存技术Redis的简单使用

    配置准备 1.添加jar包依赖 2.加入Redis配置文件spring-redis.xml redis.prope...

  • 架构师——mysql

    maven:用nexus搭建私服:上传和下载jar包依赖冲突:最短路径/最先声明/excusion spring源...

  • SpringMVC笔记

    导入jar包 我们基于Spring mvc框架进行开发,需要依赖一下的spring jar包: spring-ao...

  • Spring开发流程

    一. 导入jar包: 导入spring相关jar包 二. 创建spring的配置文件 三. 创建实体类 四. 创建...

  • spring boot 读取resources下文件 和 打成j

    spring boot 读取resources下文件 和 打成jar 读取jar包中配置文件 由于使用spring...

  • linux相关命令

    1. jar包运行,外挂配置文件:java -jar server.jar --spring.config.add...

网友评论

      本文标题:Spring依赖Jar包同名配置文件冲突

      本文链接:https://www.haomeiwen.com/subject/ezhiwhtx.html