本文共 2712 字,大约阅读时间需要 9 分钟。
在spring体系中有以下4个常用配置文件
在springboot框架下你选用一个文件配置就行了,加载顺序为
但是如果你在springcloud框架下,或者你引入springcloud-contex包的时候,你会发现你在配置层做的扩展可能会出现问题,当然也不是多大的问题,有可能你写的不太规范导致的问题,之前框架改造过程中遇到一个比较奇葩的问题,原旧框架是一套从10年开始迭代到现在的一套微服务框架,11年迭代能跟上springcloud的脚步并且框架还保持的挺干净的,不得不说这家公司是真的有实力的公司。
言归正传,这套框架有自己写的配置中心。包括其他的体系也都是自成一套体系的,原框架配置中心的其实和apollo,nacos这类体系差不多,只不过原本他们有一整套自己的加载机制,全部使用properties.load进来的配置,非常混乱,哪里使用哪里就用util去加载,导致配置散落在程序的各个角落,当然这也是一路迭代过来的问题,也可以理解,咱也不吐槽,我现在要做的事就是移除这套配置中心,改为从spring的environment获取配置,由于底层框架是他们自己的一整套体系,已经迭代到springboot体系了,但是配置还是采用一堆的propertiesUtil去加载不免不符合主流,包括框架配置文件几百个,配置项几千上万个,不免有些蛋碎,迁移成本很高,所以打算全部改成spring标准化,由于是底层框架所以加载的时候需要考虑配置加载时机的问题,这里自然就使用springboot的 提供的EnvironmentPostProcessor扩展,改完之后测试用例能正常启动注册服务,但是调试的时候发现,服务注册到zk和原本的服务不再同一个namespace下,调试了下代码发现,EnvironmentPostProcessor这个类进来了两次,进一步调试发现引入springcloud-contex包导致的,代码如下 BootstrapApplicationListener#onApplicationEvent@Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { ConfigurableEnvironment environment = event.getEnvironment(); if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, true)) { return; } // don't listen to events in a bootstrap context if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) { return; } ConfigurableApplicationContext context = null; String configName = environment .resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}"); for (ApplicationContextInitializer initializer : event.getSpringApplication() .getInitializers()) { if (initializer instanceof ParentContextApplicationContextInitializer) { context = findBootstrapContext( (ParentContextApplicationContextInitializer) initializer, configName); } } if (context == null) { context = bootstrapServiceContext(environment, event.getSpringApplication(), configName); event.getSpringApplication() .addListeners(new CloseContextOnFailureApplicationListener(context)); } apply(context, event.getSpringApplication(), environment); }
以上代码先去加载了bootstrap文件,但是我改造后的配置都写在application中,所以第一次加载的时候为空并且框架层加载的代码有个地方使用了一些死的配置就是只加载一次第二次进来这个配置就不会被变更,改造时为了不影响业务层,做了一些特殊兼容,比如将一些固定配置内置,然后原本如何加载的配置还是如何加载,但是内置的属性无法被读取,于是就写了个工具类,将内置属性塞到environment中,然后通过environment 将属性塞回到propertiesUtil中,这样就已经达到目的了,但是由于这里加载两次的原因,第一次加载到enviroment为null,但是兼容扩展塞了默认值,并且namespace默认值被util加载后不会在被刷新,所以第二次加载的时候,从配置文件读取的namespace就没有被塞到util中导致namespace不一致。当然后面加了个判断,判断application是否被加载,如果被加载才去设置util,没问题,但是这里更建议采用bootstrap配置文件的方式去做配置,更合理。毕竟是基于springcloud体系做的。就算是springboot 体系它照样也会加载springboot。所以这里得出一个不知道正不正确的结论,如果你使用springcloud体系,建议采用bootstrap体系去做配置,因为你不知道哪些基于springcloud扩展的体系需要预加载什么配置。
回头考虑要不要出个旧框架改造的专栏大家一起学习成长转载地址:http://bxkfb.baihongyu.com/