EnvironmentPostProcessor实现原理解析

EnvironmentPostProcessor实现属性文件加载原理

关于EnvironmentPostProcessor自定属性文件加载可以参考官网Customize the Environment or ApplicationContext Before It Starts
本文以springboot2.6为例,讲解EnvironmentPostProcessor实现文件加载原理,EnvironmentPostProcessor子类实现的加载本质上SpringFactoriesLoader进行类的加载,加载时机是通过ApplicationEnvironmentPreparedEvent事件监听来实现。
SpringBoot2.4以前是ConfigFileApplicationListener,SpringBoot2.4+是通过EnvironmentPostProcessorApplicationListener,SpringBoot2.4版本对外部配置进行大幅度调整,由于ConfigFileApplicationListener过于笨重职责过多替换成EnvironmentPostProcessorApplicationListener、ConfigDataEnvironmentPostProcessor来实现。

关键类方法

ConfigFileApplicationListener (SpringBoot2.4前)

org.springframework.boot.context.config.ConfigFileApplicationListener#onApplicationEnvironmentPreparedEvent方法

EnvironmentPostProcessorApplicationListener(SpringBoot2.4+)

org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent方法

详细分析

SpringBoot2.4+ 源码解析

SpringBoot启动发布ApplicationEnvironmentPreparedEvent

org.springframework.boot.SpringApplication.prepareEnvironment方法

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
        //发布ApplicationEnvironmentPreparedEvent事件
		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) {
			environment = convertEnvironment(environment);
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}
EnvironmentPostProcessorApplicationListener收到ApplicationEnvironmentPreparedEvent事件并处理EnvironmentPostProcessor子类
    //事件回调处理
	@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();
        //获取EnvironmentPostProcessors实现子类并调用postProcessEnvironment方法
		for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),
				event.getBootstrapContext())) {
			postProcessor.postProcessEnvironment(environment, application);
		}
	}

SpringBoot2.4前版本 源码解析

SpringBoot启动发布ApplicationEnvironmentPreparedEvent

org.springframework.boot.SpringApplication.prepareEnvironment方法

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
        //发布ApplicationEnvironmentPreparedEvent事件
		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) {
			environment = convertEnvironment(environment);
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}
ConfigFileApplicationListener收到ApplicationEnvironmentPreparedEvent事件并处理EnvironmentPostProcessor子类
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			onApplicationEnvironmentPreparedEvent(
					(ApplicationEnvironmentPreparedEvent) event);
		}
		if (event instanceof ApplicationPreparedEvent) {
			onApplicationPreparedEvent(event);
		}
	}

	private void onApplicationEnvironmentPreparedEvent(
			ApplicationEnvironmentPreparedEvent event) {
		List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
		postProcessors.add(this);
		AnnotationAwareOrderComparator.sort(postProcessors);
		for (EnvironmentPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessEnvironment(event.getEnvironment(),
					event.getSpringApplication());
		}
	}

总结

通过上面分析我们已清楚EnvironmentPostProcessor实现配置文件加载的原理,同时也体会到理解Spring event妙用。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值