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

springboot集成nacos讀取nacos配置數(shù)據(jù)的原理

 更新時間:2023年05月29日 09:00:25   作者:IT人的天地  
這篇文章主要介紹了springboot集成nacos讀取nacos配置數(shù)據(jù)的原理,文中有詳細的代碼流程,對大家學(xué)習(xí)springboot集成nacos有一定的幫助,需要的朋友可以參考下

1、Nacos config springboot starter包

我們在springboot應(yīng)用中集成nacos配置中心時,添加了以下依賴:

????????<dependency>
????????????<groupId>com.alibaba.boot</groupId>
????????????<artifactId>nacos-config-spring-boot-starter</artifactId>
????????????<version>0.2.11</version>
????????</dependency>

它會自動導(dǎo)入nacos-config-spring-boot-autoconfigure包和其他nacos客戶端jar包。

看到nacos-config-spring-boot-autoconfigure這種自動配置包,我們要先打開這個jar包,看下包目錄下的/META-INF/spring.factories文件,里面有如下內(nèi)容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
??com.alibaba.boot.nacos.config.autoconfigure.NacosConfigAutoConfiguration
#org.springframework.context.ApplicationContextInitializer=\
#??com.alibaba.boot.nacos.config.autoconfigure.NacosConfigApplicationContextInitializer
org.springframework.boot.env.EnvironmentPostProcessor=\
??com.alibaba.boot.nacos.config.autoconfigure.NacosConfigEnvironmentProcessor
org.springframework.context.ApplicationListener=\
??com.alibaba.boot.nacos.config.logging.NacosLoggingListener

本次我們關(guān)注的重點是org.springframework.boot.env.EnvironmentPostProcessor這個配置項的值,它只有一個值:

com.alibaba.boot.nacos.config.autoconfigure.NacosConfigEnvironmentProcessor

我們來看下NacosConfigEnvironmentProcessor這個類,它有如下定義:

public?class?NacosConfigEnvironmentProcessor
????????implements?EnvironmentPostProcessor,?Ordered?{
???????。。。。省略部分代碼
????????@Override
????public?void?postProcessEnvironment(ConfigurableEnvironment?environment,
????????????SpringApplication?application)?{
????????application.addInitializers(new?NacosConfigApplicationContextInitializer(this));
????????nacosConfigProperties?=?NacosConfigPropertiesUtils
????????????????.buildNacosConfigProperties(environment);
????????if?(enable())?{
????????????System.out.println(
????????????????????"[Nacos?Config?Boot]?:?The?preload?log?configuration?is?enabled");
????????????loadConfig(environment);
????????????NacosConfigLoader?nacosConfigLoader?=?NacosConfigLoaderFactory.getSingleton(nacosConfigProperties,?environment,?builder);
????????????LogAutoFreshProcess.build(environment,?nacosConfigProperties,?nacosConfigLoader,?builder).process();
????????}
????}
}

NacosConfigEnvironmentProcessor就做了一件事,往spring容器中添加了NacosConfigApplicationContextInitializer初始化器,后續(xù)由它完成從nacos配置中心加載數(shù)據(jù)的操作。

1.1、重要的NacosConfigEnvironmentProcessor是在哪執(zhí)行的

這個問題等我們看完下面的代碼就有了答案了~

1.2、重要的NacosConfigApplicationContextInitializer是在哪執(zhí)行的

這個問題等我們看完下面的代碼也會有答案了~

2、應(yīng)用的啟動過程

我們從以下的啟動類入手。

@SpringBootApplication
public?class?App?{
????public?static?void?main(String[]?args)?{
????????SpringApplication.run(App.class,?args);
????}
}

2.1、SpringApplication的構(gòu)造方法做了啥

跟蹤上面SpringApplication的run方法,SpringApplication.run方法內(nèi)部會先創(chuàng)建一個SpringApplication對象,然后再調(diào)用該對象的另一個run實例方法。我們先進入SpringApplication的構(gòu)造方法:

public?SpringApplication(ResourceLoader?resourceLoader,?Class<?>...?primarySources)?{
????????this.resourceLoader?=?resourceLoader;
????????Assert.notNull(primarySources,?"PrimarySources?must?not?be?null");
????????this.primarySources?=?new?LinkedHashSet<>(Arrays.asList(primarySources));
????????this.webApplicationType?=?WebApplicationType.deduceFromClasspath();
????????this.bootstrapRegistryInitializers?=?new?ArrayList<>(
????????????????getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
????????//從類路徑下面的META-INF/spring.factories文件中根據(jù)ApplicationContextInitializer配置值來初始化ApplicationContextInitializer實例
????????setInitializers((Collection)?getSpringFactoriesInstances(ApplicationContextInitializer.class));
????//從類路徑下面的META-INF/spring.factories文件中根據(jù)ApplicationListener配置值來初始化ApplicationListener實例
????????setListeners((Collection)?getSpringFactoriesInstances(ApplicationListener.class));
????????this.mainApplicationClass?=?deduceMainApplicationClass();
????}

其中g(shù)etSpringFactoriesInstances方法用于從類路徑下面的META-INF/spring.factories文件中獲取指定配置項對應(yīng)的類的全路徑名列表(多個類的全路徑名之間用英文逗號隔開),根據(jù)類的全路徑名創(chuàng)建相應(yīng)的對象。

2.1.1、構(gòu)造方法中的setInitializers方法

setInitializers方法用于設(shè)置容器的初始化器對象集合,它的參數(shù)來源于getSpringFactoriesInstances(ApplicationContextInitializer.class)的執(zhí)行結(jié)果。getSpringFactoriesInstances方法從類路徑下面的META-INF/spring.factories文件中獲取ApplicationContextInitializer對應(yīng)的類的全路徑名列表,根據(jù)類的全路徑名創(chuàng)建相應(yīng)的對象。

2.1.2、構(gòu)造方法中的setListeners方法

setListeners方法用于設(shè)置容器的ApplicationListener監(jiān)聽器對象,它的參數(shù)來源于getSpringFactoriesInstances(ApplicationListener.class)的執(zhí)行結(jié)果。getSpringFactoriesInstances方法從類路徑下面的META-INF/spring.factories文件中獲取ApplicationListener對應(yīng)的類的全路徑名列表,根據(jù)類的全路徑名創(chuàng)建相應(yīng)的對象。spring的監(jiān)聽器就是監(jiān)聽器模式的一種實現(xiàn),它可以設(shè)置自己感興趣的事件,并且在相應(yīng)事情發(fā)生時能接到通知并對該事件進行處理。我們在spring-boot.jar包下的META-INF/spring.factories可以看到如下的內(nèi)容:

#?Application?Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener

這些監(jiān)聽器類都會被實例化,并存入spring容器的ApplicationListener監(jiān)聽器列表中。

2.1.3、重要的EnvironmentPostProcessorApplicationListener出現(xiàn)了

經(jīng)過了2.1.2部分的代碼觀摩,我們知道容器的ApplicationListener監(jiān)聽器列表中已經(jīng)有了EnvironmentPostProcessorApplicationListener對象,EnvironmentPostProcessorApplicationListener很重要,它能監(jiān)聽到ApplicationEnvironmentPreparedEvent類型的事件,并且會觸發(fā)EnvironmentPostProcessor實例的執(zhí)行。我們在第1部分講到的NacosConfigEnvironmentProcessor就是個EnvironmentPostProcessor的實現(xiàn)類。此處我們先打個標(biāo)記,后面我們會說下1.1小節(jié)的NacosConfigEnvironmentProcessor實例對象是在哪執(zhí)行的。

2.2、SpringAppLication的run方法執(zhí)行流程

完成2.1節(jié)的構(gòu)造方法后,會執(zhí)行如下的run方法(本方法很重要):

????public?ConfigurableApplicationContext?run(String...?args)?{
????????long?startTime?=?System.nanoTime();
????????DefaultBootstrapContext?bootstrapContext?=?createBootstrapContext();
????????ConfigurableApplicationContext?context?=?null;
????????configureHeadlessProperty();
????????SpringApplicationRunListeners?listeners?=?getRunListeners(args);
????????listeners.starting(bootstrapContext,?this.mainApplicationClass);
????????try?{
????????????ApplicationArguments?applicationArguments?=?new?DefaultApplicationArguments(args);
????????????//準(zhǔn)備環(huán)境信息(讀取應(yīng)用系統(tǒng)需要的所有配置項)
????????????ConfigurableEnvironment?environment?=?prepareEnvironment(listeners,?bootstrapContext,?applicationArguments);
????????????configureIgnoreBeanInfo(environment);
????????????Banner?printedBanner?=?printBanner(environment);
????????????context?=?createApplicationContext();
????????????context.setApplicationStartup(this.applicationStartup);
????????????//準(zhǔn)備容器上下文
????????????prepareContext(bootstrapContext,?context,?environment,?listeners,?applicationArguments,?printedBanner);
????????????//刷新容器上下文(內(nèi)部就是執(zhí)行出名的refresh方法)
????????????refreshContext(context);
????????????。。。省略部分代碼
????????????callRunners(context,?applicationArguments);
????????}
????????。。省略部分代碼
????????return?context;
????}

結(jié)合我們本篇要說讀取nacos配置中心的原理,本次我們主要關(guān)注getRunListeners、prepareEnvironment方法和prepareContext這三個方法,我們先按照代碼的執(zhí)行順序來依次看下這幾個方法。

2.2.1、getRunListeners方法

getRunListeners方法如下:

private?SpringApplicationRunListeners?getRunListeners(String[]?args)?{
???Class<?>[]?types?=?new?Class<?>[]?{?SpringApplication.class,?String[].class?};
???return?new?SpringApplicationRunListeners(logger,
?????????getSpringFactoriesInstances(SpringApplicationRunListener.class,?types,?this,?args),
?????????this.applicationStartup);
}

它會讀取類路徑下面的META-INF/spring.factories文件中SpringApplicationRunListener配置項對應(yīng)的值,并創(chuàng)建相應(yīng)的實例對象,賦值給SpringApplicationRunListeners的listeners屬性(List類型),并返回SpringApplicationRunListeners對象。由于spring-boot包的META-INF/spring.factories文件有如下內(nèi)容:

#?Run?Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

所以SpringApplicationRunListeners的listeners屬性中就包含了EventPublishingRunListener實例對象,而且實際上只有這一個對象。

2.2.2、prepareEnvironment方法開始執(zhí)行

prepareEnvironment方法內(nèi)容如下:

private?ConfigurableEnvironment?prepareEnvironment(SpringApplicationRunListeners?listeners,
????????????DefaultBootstrapContext?bootstrapContext,?ApplicationArguments?applicationArguments)?{
????????//?Create?and?configure?the?environment
????????ConfigurableEnvironment?environment?=?getOrCreateEnvironment();
????????configureEnvironment(environment,?applicationArguments.getSourceArgs());
????????ConfigurationPropertySources.attach(environment);
????????//通過監(jiān)聽器通知環(huán)境信息已準(zhǔn)備好,觸發(fā)EnvironmentPostProcessor的執(zhí)行
????????listeners.environmentPrepared(bootstrapContext,?environment);
????????DefaultPropertiesPropertySource.moveToEnd(environment);
????????Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
????????????????"Environment?prefix?cannot?be?set?via?properties.");
????????bindToSpringApplication(environment);
????????if?(!this.isCustomEnvironment)?{
????????????EnvironmentConverter?environmentConverter?=?new?EnvironmentConverter(getClassLoader());
????????????environment?=?environmentConverter.convertEnvironmentIfNecessary(environment,?deduceEnvironmentClass());
????????}
????????ConfigurationPropertySources.attach(environment);
????????return?environment;
????}

此處劃重點,在執(zhí)行l(wèi)isteners.environmentPrepared方法之前,我們的操作系統(tǒng)環(huán)境變量、jvm系統(tǒng)屬性和業(yè)務(wù)系統(tǒng)的application.properties(以及其他的配置文件)的配置項信息都被填充到了容器的environment對象中。

2.2.1部分的getRunListeners方法返回的SpringApplicationRunListeners對象會作為參數(shù)傳遞給prepareEnvironment方法的listeners參數(shù),而listeners.environmentPrepared就是執(zhí)行SpringApplicationRunListeners的environmentPrepared方法,方法內(nèi)容如下:

//SpringApplicationRunListeners類
void?environmentPrepared(ConfigurableBootstrapContext?bootstrapContext,?ConfigurableEnvironment?environment)?{
????????doWithListeners("spring.boot.application.environment-prepared",
????????????????(listener)?->?listener.environmentPrepared(bootstrapContext,?environment));
????}

里面的doWithListeners方法最后會執(zhí)行到重載的doWithListeners方法:

//SpringApplicationRunListeners類
private?void?doWithListeners(String?stepName,?Consumer<SpringApplicationRunListener>?listenerAction,
????????????Consumer<StartupStep>?stepAction)?{
????????StartupStep?step?=?this.applicationStartup.start(stepName);
????????this.listeners.forEach(listenerAction);
????????if?(stepAction?!=?null)?{
????????????stepAction.accept(step);
????????}
????????step.end();
????}

前面2.2.1部分我們說了,listeners對象就是個list,此處它只有一個元素,是EventPublishingRunListener類型的實例對象。

listenerAction對象接收的是前面environmentPrepared方法內(nèi)部傳遞的lambda表達式:

(listener) -> listener.environmentPrepared(bootstrapContext, environment) 

當(dāng)執(zhí)行this.listeners.forEach(listenerAction)時,就會進入EventPublishingRunListener類的environmentPrepared方法:

//EventPublishingRunListener類
public?void?environmentPrepared(ConfigurableBootstrapContext?bootstrapContext,
????????????ConfigurableEnvironment?environment)?{
????????this.initialMulticaster.multicastEvent(
????????????????new?ApplicationEnvironmentPreparedEvent(bootstrapContext,?this.application,?this.args,?environment));
????}

此處會調(diào)用SimpleApplicationEventMulticaster類的multicastEvent方法,并傳遞ApplicationEnvironmentPreparedEvent事件進行廣播。

//另外此處要先說明下:當(dāng)spring創(chuàng)建EventPublishingRunListener對象的時候,就已經(jīng)將SpringApplication對象的ApplicationListener對象列表添加到了EventPublishingRunListener對象的initialMulticaster屬性的監(jiān)聽器列表中,EventPublishingRunListener構(gòu)造函數(shù)代碼如下:
public?EventPublishingRunListener(SpringApplication?application,?String[]?args)?{
????????this.application?=?application;
????????this.args?=?args;
????????this.initialMulticaster?=?new?SimpleApplicationEventMulticaster();
????????for?(ApplicationListener<?>?listener?:?application.getListeners())?{
????????????this.initialMulticaster.addApplicationListener(listener);
????????}
????}

然后我們繼續(xù)進入SimpleApplicationEventMulticaster類的multicastEvent方法:

//SimpleApplicationEventMulticaster類
public?void?multicastEvent(final?ApplicationEvent?event,?@Nullable?ResolvableType?eventType)?{
????????ResolvableType?type?=?(eventType?!=?null???eventType?:?resolveDefaultEventType(event));
????????Executor?executor?=?getTaskExecutor();
????????for?(ApplicationListener<?>?listener?:?getApplicationListeners(event,?type))?{
????????????if?(executor?!=?null)?{
????????????????executor.execute(()?->?invokeListener(listener,?event));
????????????}
????????????else?{
????????????????//會直接調(diào)用監(jiān)聽器
????????????????invokeListener(listener,?event);
????????????}
????????}
????}

這里的getApplicationListeners(event, type)會根據(jù)事件類型獲取對該事件感興趣的監(jiān)聽器列表,然后挨個調(diào)用監(jiān)聽器對象,也就是觸發(fā)各個監(jiān)聽器的處理流程。由于此處的event參數(shù)是接收了ApplicationEnvironmentPreparedEvent對象,那么getApplicationListeners方法就會獲取到EnvironmentPostProcessorApplicationListener對象(2.1.3部分咱們提到過它)。為啥呢?我們進入EnvironmentPostProcessorApplicationListener類,它有如下的supportsEventType方法:

//EnvironmentPostProcessorApplicationListener類
@Override
????public?boolean?supportsEventType(Class<??extends?ApplicationEvent>?eventType)?{
????????return?ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
????????????????||?ApplicationPreparedEvent.class.isAssignableFrom(eventType)
????????????????||?ApplicationFailedEvent.class.isAssignableFrom(eventType);
????}

supportsEventType方法就說明了該類支持處理的事件類型,里面很明確表達了它支持ApplicationEnvironmentPreparedEvent事件,所以getApplicationListeners就能把它篩選到。

我們接著上面的invokeListener方法往下看,invokeListener內(nèi)部最后會直接調(diào)用監(jiān)聽器的onApplicationEvent方法。

private?void?doInvokeListener(ApplicationListener?listener,?ApplicationEvent?event)?{
????????try?{
????????????listener.onApplicationEvent(event);
????????}
????????。。省略部分代碼
}

此處我們假定當(dāng)前的listener已經(jīng)是EnvironmentPostProcessorApplicationListener實例對象,那我們?nèi)タ纯碋nvironmentPostProcessorApplicationListener類的onApplicationEvent方法:

????@Override
????public?void?onApplicationEvent(ApplicationEvent?event)?{
????????if?(event?instanceof?ApplicationEnvironmentPreparedEvent)?{
????????????onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent)?event);
????????}
????????if?(event?instanceof?ApplicationPreparedEvent)?{
????????????onApplicationPreparedEvent();
????????}
????????if?(event?instanceof?ApplicationFailedEvent)?{
????????????onApplicationFailedEvent();
????????}
????}
????private?void?onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent?event)?{
????????ConfigurableEnvironment?environment?=?event.getEnvironment();
????????SpringApplication?application?=?event.getSpringApplication();
????????//重點,獲取所有的EnvironmentPostProcessor實例對象
????????for?(EnvironmentPostProcessor?postProcessor?:?getEnvironmentPostProcessors(application.getResourceLoader(),
????????????????event.getBootstrapContext()))?{
????????????postProcessor.postProcessEnvironment(environment,?application);
????????}
????}

上面就又出現(xiàn)了重點部分,這里會獲取所有的EnvironmentPostProcessor實例,并且挨個執(zhí)行它們的postProcessEnvironment方法,所以此時NacosConfigEnvironmentProcessor對象的postProcessEnvironment方法也就要被執(zhí)行了。

2.2.3、重要的NacosConfigEnvironmentProcessor對象終于要被執(zhí)行了

經(jīng)過了一番探索,我們在1.1小節(jié)提出的問題在此處終于有了答案~

我們來看下NacosConfigEnvironmentProcessor的postProcessEnvironment方法:

//NacosConfigEnvironmentProcessor類
@Override
????public?void?postProcessEnvironment(ConfigurableEnvironment?environment,
????????????SpringApplication?application)?{
????????//重點,往容器中添加了NacosConfigApplicationContextInitializer對象
????????application.addInitializers(new?NacosConfigApplicationContextInitializer(this));
????????nacosConfigProperties?=?NacosConfigPropertiesUtils
????????????????.buildNacosConfigProperties(environment);
????????//此方法內(nèi)部邏輯可以先忽略
????????if?(enable())?{
????????????System.out.println(
????????????????????"[Nacos?Config?Boot]?:?The?preload?log?configuration?is?enabled");
????????????loadConfig(environment);
????????????NacosConfigLoader?nacosConfigLoader?=?NacosConfigLoaderFactory.getSingleton(nacosConfigProperties,?environment,?builder);
????????????LogAutoFreshProcess.build(environment,?nacosConfigProperties,?nacosConfigLoader,?builder).process();
????????}
????}

上述代碼主要就做了一件事,往spring容器中添加了NacosConfigApplicationContextInitializer初始化器。

2.2.4、NacosConfigApplicationContextInitializer終于被加入到了spring容器中

2.1.1部分我們看到spring容器中已經(jīng)有了一批ApplicationInitializer對象。剛才2.2.3部分的NacosConfigEnvironmentProcessor又往容器中添加了一個NacosConfigApplicationContextInitializer對象。這些實現(xiàn)了ApplicationInitializer接口的對象,它們會在執(zhí)行ApplicationContext的refresh方法之前得到調(diào)用。我們繼續(xù)往下看。

2.2.5、prepareEnvironment方法執(zhí)行完成

此處只是做個標(biāo)記,咱們繼續(xù)往下看~

2.2.6、prepareContext方法開始執(zhí)行

緊接著我們就來到了run方法內(nèi)部的prepareContext方法,它的內(nèi)容如下:

????private?void?prepareContext(DefaultBootstrapContext?bootstrapContext,?ConfigurableApplicationContext?context,
????????????ConfigurableEnvironment?environment,?SpringApplicationRunListeners?listeners,
????????????ApplicationArguments?applicationArguments,?Banner?printedBanner)?{
????????context.setEnvironment(environment);
????????postProcessApplicationContext(context);
????????//執(zhí)行初始化器
????????applyInitializers(context);
????????。。。。省略部分代碼
?}

其中applyInitializers方法的代碼如下,它會挨個調(diào)用每個ApplicationContextInitializer實例的initialize方法,完成應(yīng)用上下文的初始化操作:

/**
?????*?Apply?any?{@link?ApplicationContextInitializer}s?to?the?context?before?it?is
?????*?refreshed.
?????*?@param?context?the?configured?ApplicationContext?(not?refreshed?yet)
?????*?@see?ConfigurableApplicationContext#refresh()
?????*/
????@SuppressWarnings({?"rawtypes",?"unchecked"?})
????protected?void?applyInitializers(ConfigurableApplicationContext?context)?{
????????for?(ApplicationContextInitializer?initializer?:?getInitializers())?{
????????????Class<?>?requiredType?=?GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
????????????????????ApplicationContextInitializer.class);
????????????Assert.isInstanceOf(requiredType,?context,?"Unable?to?call?initializer.");
????????????//執(zhí)行初始化器的初始化方法
????????????initializer.initialize(context);
????????}
????}

我們注意到ApplicationContextInitializer實例是從getInitializers()方法獲取的,而getInitializers()方法就是返回了容器中所有的ApplicationContextInitializer對象,當(dāng)然也包括NacosConfigApplicationContextInitializer對象。

2.2.7、重要的NacosConfigApplicationContextInitializer對象終于要被執(zhí)行了

我們看下NacosConfigApplicationContextInitializer類的initialize方法:

????@Override
????public?void?initialize(ConfigurableApplicationContext?context)?{
????????singleton.setApplicationContext(context);
????????environment?=?context.getEnvironment();
????????nacosConfigProperties?=?NacosConfigPropertiesUtils
????????????????.buildNacosConfigProperties(environment);
????????final?NacosConfigLoader?configLoader?=?NacosConfigLoaderFactory.getSingleton(
????????????????nacosConfigProperties,?environment,?builder);
????????if?(!enable())?{
????????????logger.info("[Nacos?Config?Boot]?:?The?preload?configuration?is?not?enabled");
????????}
????????else?{
????????????//?If?it?opens?the?log?level?loading?directly?will?cache
????????????//?DeferNacosPropertySource?release
????????????if?(processor.enable())?{
????????????????processor.publishDeferService(context);
????????????????configLoader
????????????????????????.addListenerIfAutoRefreshed(processor.getDeferPropertySources());
????????????}
????????????else?{
????????????????//遠程訪問nacos配置中心讀取配置數(shù)據(jù)
????????????????configLoader.loadConfig();
????????????????//設(shè)置監(jiān)聽器來監(jiān)聽nacos配置中心數(shù)據(jù)的變更并更新到本地
????????????????configLoader.addListenerIfAutoRefreshed();
????????????}
????????}
????????final?ConfigurableListableBeanFactory?factory?=?context.getBeanFactory();
????????if?(!factory
????????????????.containsSingleton(NacosBeanUtils.GLOBAL_NACOS_PROPERTIES_BEAN_NAME))?{
????????????factory.registerSingleton(NacosBeanUtils.GLOBAL_NACOS_PROPERTIES_BEAN_NAME,
????????????????????configLoader.getGlobalProperties());
????????}
????}

下面展示下NacosConfigLoader類的loadConfig方法,內(nèi)部實現(xiàn)比較易懂,就是根據(jù)我們配置的nacos的訪問地址讀取指定的dataId的數(shù)據(jù),并將其封裝為一個屬性源存放到environment對象中。

//NacosConfigLoader類?
public?void?loadConfig()?{
????????MutablePropertySources?mutablePropertySources?=?environment.getPropertySources();
????????List<NacosPropertySource>?sources?=?reqGlobalNacosConfig(globalProperties,
????????????????nacosConfigProperties.getType());
????????for?(NacosConfigProperties.Config?config?:?nacosConfigProperties.getExtConfig())?{
????????????List<NacosPropertySource>?elements?=?reqSubNacosConfig(config,
????????????????????globalProperties,?config.getType());
????????????sources.addAll(elements);
????????}
???????//如果遠程nacos的配置數(shù)據(jù)比本地配置數(shù)據(jù)的優(yōu)先級高,則執(zhí)行以下方法
????????if?(nacosConfigProperties.isRemoteFirst())?{
????????????for?(ListIterator<NacosPropertySource>?itr?=?sources.listIterator(sources.size());?itr.hasPrevious();)?{
????????????????//這里是個關(guān)鍵點,可以確保遠程的配置數(shù)據(jù)會被優(yōu)先使用
????????????????mutablePropertySources.addAfter(
????????????????????????StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,?itr.previous());
????????????}
????????}?else?{
????????????for?(NacosPropertySource?propertySource?:?sources)?{
????????????????mutablePropertySources.addLast(propertySource);
????????????}
????????}
????}

nacos屬性源被添加到容器的environment對象中的代碼如下:

MutablePropertySources?mutablePropertySources?=?environment.getPropertySources();
。。。省略部分代碼
mutablePropertySources.addAfter(
????????????????????????StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,?itr.previous());

到此為止,spring啟動所需的所有的配置項數(shù)據(jù)都已準(zhǔn)備完畢,后面spring在初始化各個bean對象的時候也能根據(jù)我們在nacos上面配置的數(shù)據(jù)來創(chuàng)建各個實例對象,比如dataSource對象~

2.2.8、prepareContext方法執(zhí)行完成

到此,容器的應(yīng)用上下文都準(zhǔn)備完畢,緊接著就會執(zhí)行大名鼎鼎的refresh方法來完成spring容器的整體創(chuàng)建過程,此處就不再贅述了。

refreshContext(context); 

以上就是springboot集成nacos讀取nacos配置數(shù)據(jù)的原理的詳細內(nèi)容,更多關(guān)于springboot集成nacos讀取數(shù)據(jù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論