Spring Cloud 2.2.2 源码之二十四BootstrapApplicationListener执行原理一

基本处理流程

在这里插入图片描述

BootstrapApplicationListener

这个是springcloud中的自动配置监听器之一,这个就是可以做远程配置的。
在这里插入图片描述
而且他排序在ConfigFileApplicationListener前面的,这个是要点,因为ConfigFileApplicationListener会进行文件的加载,如果我想添加一些新的配置文件,就可以在BootstrapApplicationListener中添加,比如bootstrap配置文件就是这么做的。
在这里插入图片描述

onApplicationEvent

看起来好像没做多少东西,其实里面重新创建了一个SpringApplication上下文呢,为了添加BootstrapImportSelectorConfiguration配置类,里面会注册所有BootstrapConfiguration类型的配置类。然后进行上下文的runConfigFileApplicationListener会去加载bootstrap的配置文件,整合初始化器到新上下文,具体慢慢分析。

public static final String BOOTSTRAP_PROPERTY_SOURCE_NAME = "bootstrap";


	@Override
	public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
		ConfigurableEnvironment environment = event.getEnvironment();
		if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class,
				true)) {//默认是true
			return;
		}
		// 不会重复执行,如果有bootstrap属性名了就返回
		if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
			return;
		}
		ConfigurableApplicationContext context = null;
		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);
	}

bootstrapServiceContext创建新上下文一

一般没有父上下文初始化,所以要重新创建一个上下文,为的就是来加载一些配置文件。
首先是创建一个新的环境,将里面的属性源删除干净,然后放入spring.config.name=bootstrap的属性源,如果有spring.config.locationspring.config.additional-location也一起放入,封装成一个MapPropertySource属性源namebootstrap,放进新环境属性源里,然后把老的环境属性源放入到新的里。

//初始化一个上下文
	private ConfigurableApplicationContext bootstrapServiceContext(
			ConfigurableEnvironment environment, final SpringApplication application,
			String configName) {
		StandardEnvironment bootstrapEnvironment = new StandardEnvironment();
		MutablePropertySources bootstrapProperties = bootstrapEnvironment
				.getPropertySources();
		for (PropertySource<?> source : bootstrapProperties) {//删除干净
			bootstrapProperties.remove(source.getName());
		}
		String configLocation = environment
				.resolvePlaceholders("${spring.cloud.bootstrap.location:}");
		String configAdditionalLocation = environment
				.resolvePlaceholders("${spring.cloud.bootstrap.additional-location:}");
		Map<String, Object> bootstrapMap = new HashMap<>();
		//添加配置名bootstrap
		bootstrapMap.put("spring.config.name", configName);
		
		bootstrapMap.put("spring.main.web-application-type", "none");
		if (StringUtils.hasText(configLocation)) {
			bootstrapMap.put("spring.config.location", configLocation);
		}
		if (StringUtils.hasText(configAdditionalLocation)) {
			bootstrapMap.put("spring.config.additional-location",
					configAdditionalLocation);
		}
		bootstrapProperties.addFirst(
				new MapPropertySource(BOOTSTRAP_PROPERTY_SOURCE_NAME, bootstrapMap));
		for (PropertySource<?> source : environment.getPropertySources()) {
			if (source instanceof StubPropertySource) {
				continue;
			}
			bootstrapProperties.addLast(source);//老的放进新的里
		}

在这里插入图片描述

bootstrapServiceContext创建新上下文二

创建一个SpringApplicationBuilder,就是建造者模式,里面就是创建SpringApplication的,然后设置一些属性,是一个最简单的一半上下文设置,然后设置一个配置文件BootstrapImportSelectorConfiguration

SpringApplicationBuilder builder = new SpringApplicationBuilder()
				.profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF)
				.environment(bootstrapEnvironment)
				// Don't use the default properties in this builder
				.registerShutdownHook(false).logStartupInfo(false)
				.web(WebApplicationType.NONE);
		final SpringApplication builderApplication = builder.application();
		if (builderApplication.getMainApplicationClass() == null) {
			builder.main(application.getMainApplicationClass());
		}
		if (environment.getPropertySources().contains("refreshArgs")) {
			builderApplication
					.setListeners(filterListeners(builderApplication.getListeners()));
		}
		builder.sources(BootstrapImportSelectorConfiguration.class);

在这里插入图片描述
在这里插入图片描述
所以等于创建了一个普通的新上下文啦。

bootstrapServiceContext创建新上下文三

SpringApplicationBuilderrun方法:
在这里插入图片描述
在这里插入图片描述
最终还是调用SpringApplicationrun,但是里面就简单的做了一件事,注册我们的BootstrapImportSelectorConfiguration配置文件,具体我们下篇说吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值