logback源码阅读(四) 为什么日志系统初始化了两次?bootstrapContext

本文详细解释了SpringBoot启动过程中的BootstrapApplicationListener和LoggingApplicationListener的区别。BootstrapApplicationListener在LoggingApplicationListener之前处理,用于初始化BootstrapContext,加载如bootstrap.properties或bootstrap.yml的配置,这些配置具有高优先级且不可被本地配置覆盖。Bootstrap上下文主要适用于SpringCloud等场景,如配置中心、加密解密属性等。而Application上下文则是常规的应用配置。了解两者的区别对于调试和配置SpringBoot应用至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

调试途中,发现初始化发生了两次,最后发现是在springboot启动的prepareEnvironment过程中,在LoggingApplicationListener执行之前,会有一个BootstrapApplicationListener先处理ApplicationEnvironmentPreparedEvent在这里插入图片描述

BootstrapApplicationListener是一个通过在单独的引导上下文(bootstrap context)中委托 ApplicationContextInitializer bean 来准备 SpringApplication(例如填充其环境)的侦听器。

bootstrap context是从 spring.factories 中定义为 BootstrapConfiguration 的源创建的 SpringApplication,此刻配置文件读到的是bootstrap.properties或bootstrap.yml的内容,而不是application.properties

public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
		ConfigurableEnvironment environment = event.getEnvironment();
		//spring.cloud.bootstrap.enabled为false则不进行引导
		if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class,
				true)) {
			return;
		}
		// don't listen to events in a bootstrap context
		if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
			return;
		}
		ConfigurableApplicationContext context = null;
		//读取{spring.cloud.bootstrap.name:bootstrap}默认是bootstrap
		String configName = environment
				.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
		for (ApplicationContextInitializer<?> initializer : event.getSpringApplication()
				.getInitializers()) {
			if (initializer instanceof ParentContextApplicationContextInitializer) {
				context = findBootstrapContext(
						(ParentContextApplicationContextInitializer) initializer,
						configName);
			}
		}
		if (context == null) {
		//创建引导类上下文环境
			context = bootstrapServiceContext(environment, event.getSpringApplication(),
					configName);
			event.getSpringApplication()
					.addListeners(new CloseContextOnFailureApplicationListener(context));
		}

		apply(context, event.getSpringApplication(), environment);
	}
  1. spring.cloud.bootstrap.enabled为false则不进行引导
  2. 读取{spring.cloud.bootstrap.name:bootstrap}默认是bootstrap作为配置文件
  3. 创建引导类上下文环境
  4. 在3中通过final ConfigurableApplicationContext context = builder.run();调用run方法

所以如果有读者调试的时候发现第一次通过LoggingApplicationListener的各个阶段找不到自己配置的logback配置文件,原因是先进行了
BootstrapApplicationListener的事件处理,此刻的配置文件和环境变量都是bootstrap的,所以读不到我们自己的配置文件和环境变量(application)

bootstrap和application有什么区别

在springcloud的源码文档中有说明

  1. Spring Cloud 构建于 Spring Boot 之上,在 Spring Boot 中有两种上下文,一种是 bootstrap,另外一种是 application
  2. application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。
  3. bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。
  4. bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。
  5. 这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。
  6. bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。
  7. boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载
  8. boostrap 里面的属性不能被覆盖

bootstrap 配置文件有以下几个应用场景:

  1. 使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;apollo做配置中心时同理
  2. 些固定的不能被覆盖的属性
  3. 些加密/解密的场景;

启动上下文时,Spring Cloud会创建一个Bootstrap Context,作为Spring应用的Application Context的父上下文。初始化的时候,Bootstrap Context==负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的Environment。Bootstrap属性有高优先级,默认情况下,它们不会被本地配置覆盖。 Bootstrap context和Application Context有着不同的约定,所以新增了一个bootstrap.yml文件,而不是使用application.yml (或者application.properties)。保证Bootstrap Context和Application Context配置的分离。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值