Spring boot外部配置(配置中心化)詳解
前言
在項目中為了靈活配置,我們常采用配置文件,常見的配置文件就比如xml和properties,springboot允許使用properties和yaml文件作為外部配置?,F(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-12Java 8 中 Map 騷操作之 merge() 的使用方法
本文簡單介紹了一下Map.merge()的方法,除此之外,Java 8 中的HashMap實現(xiàn)方法使用了TreeNode和 紅黑樹,原理很相似,今天通過本文給大家介紹Java 8 中 Map 騷操作之 merge() 的用法 ,需要的朋友參考下吧2021-07-07jackson json序列化實現(xiàn)首字母大寫,第二個字母需小寫
這篇文章主要介紹了jackson json序列化實現(xiàn)首字母大寫,第二個字母需小寫方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Java代碼實現(xiàn)哈希表(google 公司的上機題)
這篇文章主要介紹了Java 哈希表詳解(google 公司的上機題),本文通過圖文實例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03