Spring boot外部配置(配置中心化)詳解
前言
在項(xiàng)目中為了靈活配置,我們常采用配置文件,常見的配置文件就比如xml和properties,springboot允許使用properties和yaml文件作為外部配置?,F(xiàn)在編譯器對(duì)于yaml語言的支持還不夠好,目前還是使用properties文件作為外部配置。
在Spring cloud config出來之前, 自己實(shí)現(xiàn)了基于ZK的配置中心, 杜絕了本地properties配置文件, 原理很簡(jiǎn)單, 只是重載了PropertyPlaceholderConfigurer的mergeProperties()
:
/** * 重載合并屬性實(shí)現(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; }
這個(gè)實(shí)現(xiàn)在spring項(xiàng)目里用起來還是挺順手的, 但是近期部分spring-boot項(xiàng)目里發(fā)現(xiàn)這種placeholder的實(shí)現(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)其會(huì)檢查Java system propeties里的屬性, 也就是說, 只要把mergerProperties讀到的屬性寫入Java system props里即可, 看了下源碼, 找到個(gè)切入點(diǎn)
/** * 重載處理屬性實(shí)現(xiàn) * 根據(jù)選項(xiàng), 決定是否將合并后的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è)置了個(gè)開關(guān), 是否寫入系統(tǒng)屬性, 如果是spring boot的項(xiàng)目, 就開啟, 這樣對(duì)線上非spring boot項(xiàng)目做到影響最小, 然后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é)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解,一些常用的工具類、線程池、緩存,數(shù)據(jù)庫,數(shù)據(jù)庫連接池、賬戶登錄系統(tǒng)、配置文件等程序中可能只允許我們創(chuàng)建一個(gè)對(duì)象,這就需要單例模式,需要的朋友可以參考下2023-12-12動(dòng)態(tài)上傳jar包熱部署的實(shí)戰(zhàn)詳解
開發(fā)系統(tǒng)過程中遇到的一個(gè)需求,系統(tǒng)給定一個(gè)接口,用戶可以自定義開發(fā)該接口的實(shí)現(xiàn),并將實(shí)現(xiàn)打成jar包,上傳到系統(tǒng)中。系統(tǒng)完成熱部署,并切換該接口的實(shí)現(xiàn)。本文詳細(xì)介紹了實(shí)現(xiàn)方法,需要的可以參考一下2022-10-10Java 8 中 Map 騷操作之 merge() 的使用方法
本文簡(jiǎn)單介紹了一下Map.merge()的方法,除此之外,Java 8 中的HashMap實(shí)現(xiàn)方法使用了TreeNode和 紅黑樹,原理很相似,今天通過本文給大家介紹Java 8 中 Map 騷操作之 merge() 的用法 ,需要的朋友參考下吧2021-07-07Java實(shí)現(xiàn)的AES256加密解密功能示例
這篇文章主要介紹了Java實(shí)現(xiàn)的AES256加密解密功能,結(jié)合完整實(shí)例形式分析了Java實(shí)現(xiàn)AES256加密解密功能的步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-02-02關(guān)于replaceFirst使用時(shí)的注意事項(xiàng)
這篇文章主要介紹了關(guān)于replaceFirst使用時(shí)的注意事項(xiàng),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03jackson json序列化實(shí)現(xiàn)首字母大寫,第二個(gè)字母需小寫
這篇文章主要介紹了jackson json序列化實(shí)現(xiàn)首字母大寫,第二個(gè)字母需小寫方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Java代碼實(shí)現(xiàn)哈希表(google 公司的上機(jī)題)
這篇文章主要介紹了Java 哈希表詳解(google 公司的上機(jī)題),本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03