又是美好的一天呀~
个人博客地址: huanghong.top
往下看看~
内容简介
SpringCloud服务在主程序启动时,会在刷新上下文之前通过扩展点初始化器ApplicationContextInitializer的initialize方法来进行环境相关内容的准备,PropertySourceBootstrapConfiguration作为ApplicationContextInitializer的实现类,在环境准备期间会通过PropertySourceLocator接口在程序启动前来获取应用属性资源并加载到当前Environment中。
eg. SpringCloud在整合Nacos(Config)配置中心,应用在启动过程中会执行Nacos实现的NacosPropertySourceLocator来获取Nacos服务端配置内容并将配置内容加载进当前Environment中,从而实现配置属性的注入功能。
源码分析
prepareContext
应用主程序启动后,在执行至refreshContext刷新上下文之前,首先会进行上下文内容的准备工作。
//org.springframework.boot.SpringApplication#prepareContext
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//上下文环境设置
context.setEnvironment(environment);
//上下文扩展
//1. 手动注入beanNameGenerator实例
//2. 设置上下文资源加载器resourceLoader
//3. 设置转换服务ConversionService
postProcessApplicationContext(context);
//执行初始化器初始化内容
applyInitializers(context);
...
}
applyInitializers
//org.springframework.boot.SpringApplication#applyInitializers
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.");
//执行初始化器初始化方法
initializer.initialize(context);
}
}
PropertySourceBootstrapConfiguration#initialize
//org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration#initialize
public void initialize(ConfigurableApplicationContext applicationContext) {
List<PropertySource<?>> composite = new ArrayList<>();
//propertySourceLocators进行排序
AnnotationAwareOrderComparator.sort(this.propertySourceLocators);
boolean empty = true;
//获取上下文环境对象
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//遍历处理
for (PropertySourceLocator locator : this.propertySourceLocators) {
//获取PropertySource集合
Collection<PropertySource<?>> source = locator.locateCollection(environment);
if (source == null || source.size() == 0) {
continue;
}
List<PropertySource<?>> sourceList = new ArrayList<>();
//遍历PropertySource集合
for (PropertySource<?> p : source) {
//如果为EnumerablePropertySource类型对象, 则构建一个BootstrapPropertySource实例添加进集合中
if (p instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) p;
sourceList.add(new BootstrapPropertySource<>(enumerable));
}
else {
//否则构建一个SimpleBootstrapPropertySource实例并添加进集合中
sourceList.add(new SimpleBootstrapPropertySource(p));
}
}
logger.info("Located property source: " + sourceList);
composite.addAll(sourceList);
empty = false;
}
//获取属性集合不为空
if (!empty) {
//获取当前环境所有属性源
MutablePropertySources propertySources = environment.getPropertySources();
String logConfig = environment.resolvePlaceholders("${logging.config:}");
LogFile logFile = LogFile.get(environment);
for (PropertySource<?> p : environment.getPropertySources()) {
//移除bootstrapProperties相关属性源
if (p.getName().startsWith(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
propertySources.remove(p.getName());
}
}
//添加上文获取到的属性源集合至当前环境中
insertPropertySources(propertySources, composite);
//重新初始化日志系统
reinitializeLoggingSystem(environment, logConfig, logFile);
//设置日志等级
setLogLevels(applicationContext, environment);
//处理指定环境 TODO
handleIncludedProfiles(environment);
}
}
locateCollection
//org.springframework.cloud.bootstrap.config.PropertySourceLocator#locateCollection(org.springframework.cloud.bootstrap.config.PropertySourceLocator, org.springframework.core.env.Environment)
static Collection<PropertySource<?>> locateCollection(PropertySourceLocator locator, Environment environment) {
//执行具体实现方法返回PropertySource对象
PropertySource<?> propertySource = locator.locate(environment);
if (propertySource == null) {
return Collections.emptyList();
}
//如果是复合对象(对象中包含多个PropertySource),过滤空值并逐个添加返回
if (CompositePropertySource.class.isInstance(propertySource)) {
Collection<PropertySource<?>> sources = ((CompositePropertySource) propertySource).getPropertySources();
List<PropertySource<?>> filteredSources = new ArrayList<>();
for (PropertySource<?> p : sources) {
if (p != null) {
filteredSources.add(p);
}
}
return filteredSources;
}
else {
//返回结果集
return Arrays.asList(propertySource);
}
}
Nacos示例
当前Environment持有的PropertySource
insertPropertySources
//org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration#insertPropertySources
private void insertPropertySources(MutablePropertySources propertySources, List<PropertySource<?>> composite) {
MutablePropertySources incoming = new MutablePropertySources();
List<PropertySource<?>> reversedComposite = new ArrayList<>(composite);
// Reverse the list so that when we call addFirst below we are maintaining the
// same order of PropertySources
// Wherever we call addLast we can use the order in the List since the first item
// will end up before the rest
//反转集合,后续可以按照原顺序加入当前环境集合中
Collections.reverse(reversedComposite);
for (PropertySource<?> p : reversedComposite) {
incoming.addFirst(p);
}
//overrideSystemProperties: 外部属性可以覆盖系统属性 默认true
//allowOverride: 允许覆盖 默认true
//overrideNone: 当allowOverride为true时,外部属性应该具有最低优先级,并且不应该覆盖任何现有的属性源(包括本地配置文件)
PropertySourceBootstrapProperties remoteProperties = new PropertySourceBootstrapProperties();
Binder.get(environment(incoming)).bind("spring.cloud.config", Bindable.ofInstance(remoteProperties));
//默认赋值方式
if (!remoteProperties.isAllowOverride()
|| (!remoteProperties.isOverrideNone() && remoteProperties.isOverrideSystemProperties())) {
for (PropertySource<?> p : reversedComposite) {
//添加进当前环境属性源中
propertySources.addFirst(p);
}
return;
}
if (remoteProperties.isOverrideNone()) {
for (PropertySource<?> p : composite) {
propertySources.addLast(p);
}
return;
}
if (propertySources.contains(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) {
if (!remoteProperties.isOverrideSystemProperties()) {
for (PropertySource<?> p : reversedComposite) {
propertySources.addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, p);
}
}
else {
for (PropertySource<?> p : composite) {
propertySources.addBefore(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, p);
}
}
}
else {
for (PropertySource<?> p : composite) {
propertySources.addLast(p);
}
}
}
ConfigurationProperties
基于ConfigurationProperties的属性填充是发生在Bean初始化的期间,Bean属性的配置填充是通过ConfigurationPropertiesBindingPostProcessor#postProcessBeforeInitialization来完成的。
postProcessBeforeInitialization
//org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor#postProcessBeforeInitialization
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
bind(ConfigurationPropertiesBean.get(this.applicationContext, bean, beanName));
return bean;
}
bind
//org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor#bind
private void bind(ConfigurationPropertiesBean bean) {
if (bean == null || hasBoundValueObject(bean.getName())) {
return;
}
Assert.state(bean.getBindMethod() == BindMethod.JAVA_BEAN, "Cannot bind @ConfigurationProperties for bean '"
+ bean.getName() + "'. Ensure that @ConstructorBinding has not been applied to regular bean");
try {
//通过配置文件中的配置属性重新绑定Bean的属性值
this.binder.bind(bean);
}
catch (Exception ex) {
throw new ConfigurationPropertiesBindException(bean, ex);
}
}
感谢阅读完本篇文章!!!
个人博客地址: huanghong.top