Spring boot外部配置(配置中心化)詳解
前言
在項目中為了靈活配置,我們常采用配置文件,常見的配置文件就比如xml和properties,springboot允許使用properties和yaml文件作為外部配置。現(xiàn)在編譯器對于yaml語言的支持還不夠好,目前還是使用properties文件作為外部配置。
在Spring cloud config出來之前, 自己實現(xiàn)了基于ZK的配置中心, 杜絕了本地properties配置文件, 原理很簡單, 只是重載了PropertyPlaceholderConfigurer的mergeProperties() :
/**
* 重載合并屬性實現(xiàn)
* 先加載file properties, 然后并入ZK配置中心讀取的properties
*
* @return 合并后的屬性集合
* @throws IOException 異常
*/
@Override
protected Properties mergeProperties() throws IOException {
Properties result = new Properties();
// 加載父類的配置
Properties mergeProperties = super.mergeProperties();
result.putAll(mergeProperties);
// 加載從zk中讀取到的配置
Map<String, String> configs = loadZkConfigs();
result.putAll(configs);
return result;
}
這個實現(xiàn)在spring項目里用起來還是挺順手的, 但是近期部分spring-boot項目里發(fā)現(xiàn)這種placeholder的實現(xiàn)跟spring boot的@ConfigurationProperties(prefix = "xxx") 不能很好的配合工作,
也就是屬性沒有被resolve處理, 用@Value的方式確可以讀到, 但是@Value配置起來如果屬性多的話還是挺繁瑣的, 還是傾向用@ConfigurationProperties的prefix, 于是看了下spring boot的文檔發(fā)現(xiàn) PropertySource
order:
* Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
* @TestPropertySource annotations on your tests.
* @SpringBootTest#properties annotation attribute on your tests.
* Command line arguments.
* Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
* ServletConfig init parameters.
* ServletContext init parameters.
* JNDI attributes from java:comp/env.
* Java System properties (System.getProperties()).
* OS environment variables.
* A RandomValuePropertySource that only has properties in random.*.
* Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
* Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
* Application properties outside of your packaged jar (application.properties and YAML variants).
* Application properties packaged inside your jar (application.properties and YAML variants).
* @PropertySource annotations on your @Configuration classes.
* Default properties (specified using SpringApplication.setDefaultProperties).
不難發(fā)現(xiàn)其會檢查Java system propeties里的屬性, 也就是說, 只要把mergerProperties讀到的屬性寫入Java system props里即可, 看了下源碼, 找到個切入點
/**
* 重載處理屬性實現(xiàn)
* 根據(jù)選項, 決定是否將合并后的props寫入系統(tǒng)屬性, Spring boot需要
*
* @param beanFactoryToProcess
* @param props 合并后的屬性
* @throws BeansException
*/
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
// 原有邏輯
super.processProperties(beanFactoryToProcess, props);
// 寫入到系統(tǒng)屬性
if (writePropsToSystem) {
// write all properties to system for spring boot
Enumeration<?> propertyNames = props.propertyNames();
while (propertyNames.hasMoreElements()) {
String propertyName = (String) propertyNames.nextElement();
String propertyValue = props.getProperty(propertyName);
System.setProperty(propertyName, propertyValue);
}
}
}
為避免影響過大, 設(shè)置了個開關(guān), 是否寫入系統(tǒng)屬性, 如果是spring boot的項目, 就開啟, 這樣對線上非spring boot項目做到影響最小, 然后spring boot的@ConfigurationProperties完美讀到屬性;
具體代碼見: org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
ConfigurationProperties annotation = AnnotationUtils
.findAnnotation(bean.getClass(), ConfigurationProperties.class);
if (annotation != null) {
postProcessBeforeInitialization(bean, beanName, annotation);
}
annotation = this.beans.findFactoryAnnotation(beanName,
ConfigurationProperties.class);
if (annotation != null) {
postProcessBeforeInitialization(bean, beanName, annotation);
}
return bean;
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Java設(shè)計模式之單例模式Singleton Pattern詳解
這篇文章主要介紹了Java設(shè)計模式之單例模式Singleton Pattern詳解,一些常用的工具類、線程池、緩存,數(shù)據(jù)庫,數(shù)據(jù)庫連接池、賬戶登錄系統(tǒng)、配置文件等程序中可能只允許我們創(chuàng)建一個對象,這就需要單例模式,需要的朋友可以參考下2023-12-12
Java 8 中 Map 騷操作之 merge() 的使用方法
本文簡單介紹了一下Map.merge()的方法,除此之外,Java 8 中的HashMap實現(xiàn)方法使用了TreeNode和 紅黑樹,原理很相似,今天通過本文給大家介紹Java 8 中 Map 騷操作之 merge() 的用法 ,需要的朋友參考下吧2021-07-07
jackson json序列化實現(xiàn)首字母大寫,第二個字母需小寫
這篇文章主要介紹了jackson json序列化實現(xiàn)首字母大寫,第二個字母需小寫方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
Java代碼實現(xiàn)哈希表(google 公司的上機題)
這篇文章主要介紹了Java 哈希表詳解(google 公司的上機題),本文通過圖文實例相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03

