文章24 | 阅读 12811 | 点赞0
接着上篇,我们看BootstrapImportSelectorConfiguration配置类:
@Configuration(proxyBeanMethods = false)
@Import(BootstrapImportSelector.class)
public class BootstrapImportSelectorConfiguration {
}
Import了一个Selector:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
List<String> names = new ArrayList<>(SpringFactoriesLoader
.loadFactoryNames(BootstrapConfiguration.class, classLoader));
names.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(
this.environment.getProperty("spring.cloud.bootstrap.sources", ""))));
List<OrderedAnnotatedElement> elements = new ArrayList<>();
for (String name : names) {
try {
elements.add(
new OrderedAnnotatedElement(this.metadataReaderFactory, name));
}
catch (IOException e) {
continue;
}
}
AnnotationAwareOrderComparator.sort(elements);
String[] classNames = elements.stream().map(e -> e.name).toArray(String[]::new);
return classNames;
}
可以看到,类似SpringBoot的EnableAutoConfiguration,主要是加载自动配置的BootstrapConfiguration
类型的配置类。
说明什么呢?SpringCloud通过BootstrapConfiguration来进行新的上下文的配置自动装配。
新的上下文执行run的时候,也会有环境准备过程,同样也会触发环境准备好的事件监听,此时会调用到ConfigFileApplicationListener的监听方法,此时因为设置了bootstrap
属性源,那么就会去加载bootstrap
的相关配置文件,然后再去处理BootstrapImportSelectorConfiguration
的解析
然后我们看一下spring-cloud-alibaba-nacos-config里的spring.factories:
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.NacosConfigBootstrapConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.nacos.NacosConfigAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer
可以看到定义了NacosConfigBootstrapConfiguration类,作为BootstrapConfiguration自动配置。
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigBootstrapConfiguration {
@Bean
@ConditionalOnMissingBean
public NacosConfigProperties nacosConfigProperties() {
return new NacosConfigProperties();
}
@Bean
@ConditionalOnMissingBean
public NacosConfigManager nacosConfigManager(
NacosConfigProperties nacosConfigProperties) {
return new NacosConfigManager(nacosConfigProperties);
}
@Bean
public NacosPropertySourceLocator nacosPropertySourceLocator(
NacosConfigManager nacosConfigManager) {
return new NacosPropertySourceLocator(nacosConfigManager);
}
}
这里定义了几个实例:NacosConfigProperties、NacosConfigManager、NacosPropertySourceLocator,后面会去分析。
再回到BootstrapApplicationListener的bootstrapServiceContext方法,当新的上下文run完成后,会添加一个初始化器AncestorInitializer
,里面创建了一个ParentContextApplicationContextInitializer,通过这个建立新的上下文和原上下文的父子关系。这样下次就可以直接取出来用,不用需要重新创建上下文了,然后删除bootstrap
属性源。最后对老环境的属性源进行整合:
mergeDefaultProperties(environment.getPropertySources(), bootstrapProperties);
private void mergeDefaultProperties(MutablePropertySources environment,
MutablePropertySources bootstrap) {
String name = DEFAULT_PROPERTIES;
if (bootstrap.contains(name)) {
PropertySource<?> source = bootstrap.get(name);
if (!environment.contains(name)) {
environment.addLast(source);
}
else {
PropertySource<?> target = environment.get(name);
if (target instanceof MapPropertySource && target != source
&& source instanceof MapPropertySource) {
Map<String, Object> targetMap = ((MapPropertySource) target)
.getSource();
Map<String, Object> map = ((MapPropertySource) source).getSource();
for (String key : map.keySet()) {
if (!target.containsProperty(key)) {
targetMap.put(key, map.get(key));
}
}
}
}
}
mergeAdditionalPropertySources(environment, bootstrap);
}
private void mergeAdditionalPropertySources(MutablePropertySources environment,
MutablePropertySources bootstrap) {
PropertySource<?> defaultProperties = environment.get(DEFAULT_PROPERTIES);
ExtendedDefaultPropertySource result = defaultProperties instanceof ExtendedDefaultPropertySource
? (ExtendedDefaultPropertySource) defaultProperties
: new ExtendedDefaultPropertySource(DEFAULT_PROPERTIES,
defaultProperties);
for (PropertySource<?> source : bootstrap) {
if (!environment.contains(source.getName())) {
result.add(source);
}
}
for (String name : result.getPropertySourceNames()) {
bootstrap.remove(name);
}
addOrReplace(environment, result);
addOrReplace(bootstrap, result);
}
private void addOrReplace(MutablePropertySources environment,
PropertySource<?> result) {
if (environment.contains(result.getName())) {
environment.replace(result.getName(), result);
}
else {
environment.addLast(result);
}
}
之后再在原上下文中添加监听器CloseContextOnFailureApplicationListener
event.getSpringApplication()
.addListeners(new CloseContextOnFailureApplicationListener(context));
然后是apply方法:
private void apply(ConfigurableApplicationContext context,
SpringApplication application, ConfigurableEnvironment environment) {
if (application.getAllSources().contains(BootstrapMarkerConfiguration.class)) {
return;
}
application.addPrimarySources(Arrays.asList(BootstrapMarkerConfiguration.class));
@SuppressWarnings("rawtypes")
Set target = new LinkedHashSet<>(application.getInitializers());
target.addAll(
getOrderedBeansOfType(context, ApplicationContextInitializer.class));
application.setInitializers(target);
addBootstrapDecryptInitializer(application);
}
在原上下文中添加一个标记配置类BootstrapMarkerConfiguration
,标记bootstrap
处理已经完成。然后再对初始化器排序。
到这里BootstrapApplicationListener的执行过程就分析完了。简单来说就是创建了一个新的上下文并作为原上下文的父级,然后进行bootstrap配置文件加载。
同时引入BootstrapConfiguration进行Bootstrap上下文的自动装配。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_19414183/article/details/112242898
内容来源于网络,如有侵权,请联系作者删除!