欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot擴展外部化配置的原理解析

 更新時間:2021年03月16日 09:44:31   作者:brucelwl  
這篇文章主要介紹了SpringBoot擴展外部化配置的原理解析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

Environment實現(xiàn)原理

在基于SpringBoot開發(fā)的應用中,我們常常會在application.properties、application-xxx.properties、application.ymlapplication-xxx.yml等配置文件中設置一些屬性值,然后通過@Value@ConfigurationProperties等注解獲取,或者采用編碼的方式通過Environment獲取。

# application.properties
my.config.appId=demo
@RestController
public class WebController {

 @Value("${my.config.appId}")
 private String appId;

 @Autowired
 private Environment env;

 @Autowired
 private ConfigurableEnvironment environment;

 @GetMapping("/appInfo")
 public String appInfo() {
  System.out.println(environment.getProperty("my.config.appId"));
  System.out.println(env.getProperty("my.config.appId"));
  System.out.println(appId);
  System.out.println(env == environment); //true
  return appId;
 }
}

實際上envenvironment是同一個對象,在Spring中ConfigurableEnvironmentEnvironment的子類,具體實現(xiàn)類全部是通過implements ConfigurableEnvironment接口來實現(xiàn),所以所有可以拿到Environment接口地方都可以強制轉(zhuǎn)換為ConfigurableEnvironment

ConfigurableEnvironment繼承Environment,Environment繼承PropertyResolver,主要提供了對屬性獲取方法,AbstractEnvironment做為抽象類實現(xiàn)了ConfigurableEnvironment接口方法,其內(nèi)部是通過org.springframework.core.env.MutablePropertySources來保存不同類型的屬性資源。而MutablePropertySources內(nèi)部實際上就是List<PropertySource<?>>集合

在這里插入圖片描述

public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
	void setActiveProfiles(String... profiles);
	void addActiveProfile(String profile);
	void setDefaultProfiles(String... profiles);

 //MutablePropertySources 內(nèi)部實際上就是**List<PropertySource<?>>集合
	MutablePropertySources getPropertySources();

	Map<String, Object> getSystemProperties();
	Map<String, Object> getSystemEnvironment();
	void merge(ConfigurableEnvironment parent);
}

PropertySource是什么呢?

其實就是一個key-value集合,key就是一個配置項,value就是配置的值。
例如: 通過System.getProperties()得到的系統(tǒng)屬性就是一種類型的PropertySource,通過application.yml配置的屬性是另一種屬性資源。當調(diào)用env.getProperty()獲取屬性值時,會遍歷PropertySource集合,只要有一個PropertySource中有對應屬性值則不再繼續(xù)遍歷查找,所以在集合中越靠前的屬性優(yōu)先級越高。

獲取某個配置項值的訪問方式,源碼如下:
org.springframework.core.env.PropertySourcesPropertyResolver#getProperty(java.lang.String, java.lang.Class<T>, boolean)

protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
	if (this.propertySources != null) {
		for (PropertySource<?> propertySource : this.propertySources) {
			if (logger.isTraceEnabled()) {
				logger.trace("Searching for key '" + key + "' in PropertySource '" + propertySource.getName() + "'");
			}
			Object value = propertySource.getProperty(key);
			if (value != null) {
				if (resolveNestedPlaceholders && value instanceof String) {
					value = resolveNestedPlaceholders((String) value);
				}
				logKeyFound(key, propertySource, value);
				return convertValueIfNecessary(value, targetValueType);
			}
		}
	}
	if (logger.isTraceEnabled()) {
		logger.trace("Could not find key '" + key + "' in any property source");
	}
	return null;
}

如何擴展自己的外部化配置?

實際上我們可以利用SpringBoot中的擴展點,拿到ConfigurableEnvironment對象來獲取到MutablePropertySources,添加自己的PropertySource就行,例如可以訪問一個http接口,獲取外部化配置。

在這里插入圖片描述

擴展接口及優(yōu)先級如下

梯形縮進表示內(nèi)部調(diào)用了下面的接口實現(xiàn)

1.org.springframework.boot.SpringApplicationRunListener#environmentPrepared(ConfigurableBootstrapContext, ConfigurableEnvironment)

1.ApplicationListener< org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent> EnvironmentPostProcessorApplicationListener

1. org.springframework.boot.env.EnvironmentPostProcessor 1.org.springframework.boot.context.config.ConfigDataLoader 1.org.springframework.boot.env.PropertySourceLoader 1.org.springframework.context.ApplicationContextInitializer#initialize

1.org.springframework.boot.SpringApplicationRunListener#contextPrepared 4.org.springframework.boot.context.event.ApplicationPreparedEvent 5.org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistryorg.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory

但是在4.BeanDefinitionRegistryPostProcessor和5.BeanFactoryPostProcessor中擴展時機比較晚,這個時候已經(jīng)執(zhí)行完包掃描,如果在這個時機添加自己的外部化配置,對于注解@ConditionalOnProperty可能大部分不會生效。

Apollo配置中心客戶端和SpringBoot的整合實現(xiàn)

Apollo配置中心客戶端是如何與SpringBoot整合的?

開源的Apollo配置中心默認啟動就是通過BeanFactoryPostProcessor來擴展apollo上的配置到Spring的Environment中,
@EnableApolloConfig 注解向Spring中導入了bean com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor,PropertySourcesProcessor同時實現(xiàn)了org.springframework.core.PriorityOrdered并設置了最高的執(zhí)行優(yōu)先級Ordered.HIGHEST_PRECEDENCE,但是由于包掃描已經(jīng)在PropertySourcesProcessor之前執(zhí)行完成,所以即使設置了最高優(yōu)先級,同樣無法解決在Spring執(zhí)行包掃描階段訪問不到apllo上的配置問題。

因此在SpringBoot項目中,apollo提供了另一種啟動方式,使用配置項apollo.bootstrap.enabled = true來解決,實現(xiàn)類為com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer,其主要是通過實現(xiàn)第2個擴展接口org.springframework.context.ApplicationContextInitializer來提前將apollo的PropertySource添加到Spring的Environment中。
這樣我們就可以通過Environment來獲取到apollo中的配置項值。而@ConditionalOnProperty則是從Environment獲取屬性值來判斷的條件是否成立,因此使用該接口擴展Environment,@ConditionalOnProperty注解則可以在啟動階段正常訪問到apollo中的配置項。

到此這篇關于SpringBoot擴展外部化配置的原理解析的文章就介紹到這了,更多相關SpringBoot擴展外部化配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 在Spring Boot中使用Spring-data-jpa實現(xiàn)分頁查詢

    在Spring Boot中使用Spring-data-jpa實現(xiàn)分頁查詢

    如何使用jpa進行多條件查詢以及查詢列表分頁呢?下面我將介紹兩種多條件查詢方式。具體實例代碼大家參考下本文吧
    2017-07-07
  • java 操作gis geometry類型數(shù)據(jù)方式

    java 操作gis geometry類型數(shù)據(jù)方式

    這篇文章主要介紹了java 操作gis geometry類型數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 通過代碼實例深入解析Java重寫和重載

    通過代碼實例深入解析Java重寫和重載

    這篇文章主要介紹了通過代碼實例深入解析Java重寫和重載,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • java設置session過期時間的實現(xiàn)方法

    java設置session過期時間的實現(xiàn)方法

    這篇文章主要介紹了java設置session過期時間的實現(xiàn)方法,以實例形式詳細講述了具體實現(xiàn)過程,非常具有參考借鑒價值,需要的朋友可以參考下
    2014-10-10
  • 基于@AliasFor注解的用法及說明

    基于@AliasFor注解的用法及說明

    這篇文章主要介紹了基于@AliasFor注解的用法及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Java基礎之Unsafe內(nèi)存操作不安全類詳解

    Java基礎之Unsafe內(nèi)存操作不安全類詳解

    Java是面向?qū)ο笳Z言,在使用Java編程時,大多數(shù)情況下都不會直接操作內(nèi)存,而且Java也不提倡直接操作內(nèi)存,但是Java中到底有沒有可以直接操作內(nèi)存的工具類呢?有!Java中提供Unsafe類可以用來來直接操作內(nèi)存,文中詳細介紹了Unsafe內(nèi)存操作不安全類,需要的朋友可以參考下
    2021-06-06
  • Java學習筆記之Maven篇

    Java學習筆記之Maven篇

    今天來回顧下Java學習筆記,文中對maven的核心,maven的結(jié)構(gòu)以及maven能做什么都作出了詳細的解釋,,需要的朋友可以參考下
    2021-05-05
  • Java編譯錯誤信息提示java.lang.ExceptionInInitializer解決

    Java編譯錯誤信息提示java.lang.ExceptionInInitializer解決

    這篇文章主要介紹了Java編譯錯誤信息提示java.lang.ExceptionInInitializer的分析講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • springboot -sse -flux 服務器推送消息的方法

    springboot -sse -flux 服務器推送消息的方法

    這篇文章主要介紹了springboot -sse -flux 服務器推送消息的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-11-11
  • java基礎之字符串編碼知識點總結(jié)

    java基礎之字符串編碼知識點總結(jié)

    這篇文章主要介紹了java基礎之字符串編碼總結(jié),文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有很好的幫助,要的朋友可以參考下
    2021-04-04

最新評論