SpringBoot源码分析之-启动流程分析四(prepareEnvironment 环境准备)

环境准备流程

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		//创建环境ConfigurableEnvironment   根据项目类型
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		//设置PropertySources和activeProfiles(环境中获取) 
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		//把PropertySources设置在自己PropertySources第一个位置
		ConfigurationPropertySources.attach(environment);
		//广播事件ApplicationEnvironmentPreparedEvent
		listeners.environmentPrepared(environment);
		// SpringApplication绑定环境 spring.main*
		bindToSpringApplication(environment);
		// 将环境进行转换
		// web环境是StandardServletEnvironment 已经是StandardEnvironment的子类了,所以不用新建
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		//移除,再把environment设置在第一个位置
		ConfigurationPropertySources.attach(environment);
		return environment;
	}
	

1.web项目环境 ->StandardServletEnvironment

	ConfigurableEnvironment environment = getOrCreateEnvironment();
	//也就是之前将的构造的项目类型我的是servlet web
	private ConfigurableEnvironment getOrCreateEnvironment() {
			if (this.environment != null) {
				return this.environment;
			}
			switch (this.webApplicationType) {
			case SERVLET:
				return new StandardServletEnvironment();
			case REACTIVE:
				return new StandardReactiveWebEnvironment();
			default:
				return new StandardEnvironment();
			}
		}	

在这里插入图片描述
在这里插入图片描述

初始化几个配置源

servletConfigInitParams     ->servletConfig初始化参数
servletContextInitParams    ->servletContext初始化参数
jndiProperties		        ->JNDI
systemProperties            ->System.getProperties()  //当前的系统属性
systemEnvironment           ->System.getenv()         //所有的环境变量

2.configureEnvironment(environment, applicationArguments.getSourceArgs());

	protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
		if (this.addConversionService) {
			//一些转换服务
			ConversionService conversionService = ApplicationConversionService.getSharedInstance();
			environment.setConversionService((ConfigurableConversionService) conversionService);
		}
		configurePropertySources(environment, args);
		configureProfiles(environment, args);
	}

	//从当前环境中找spring.profiles.active, 设置activeProfiles
    //configureProfiles -> environment.getActiveProfiles() -> doGetActiveProfiles()
	public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";
	
	protected Set<String> doGetActiveProfiles() {
		synchronized (this.activeProfiles) {
			if (this.activeProfiles.isEmpty()) {
				String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
				if (StringUtils.hasText(profiles)) {
					setActiveProfiles(StringUtils.commaDelimitedListToStringArray(
							StringUtils.trimAllWhitespace(profiles)));
				}
			}
			return this.activeProfiles;
		}
	}

3. ConfigurationPropertySources.attach(environment);

把PropertySources加到成自己PropertySources的第一个位置

public static void attach(Environment environment) {
		Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
		MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
		PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
		if (attached != null && attached.getSource() != sources) {
			sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
			attached = null;
		}
		if (attached == null) {
			sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
					new SpringConfigurationPropertySources(sources)));
		}
	}

4.广播事件ApplicationEnvironmentPreparedEvent

0 = {ConfigFileApplicationListener@2349} 
1 = {AnsiOutputApplicationListener@2350} 
2 = {LoggingApplicationListener@2351} 
3 = {ClasspathLoggingApplicationListener@2352} 
4 = {BackgroundPreinitializer@2353} 
5 = {DelegatingApplicationListener@2354} 
6 = {FileEncodingApplicationListener@2355} 

其中一个加载配置文件的监听器
ConfigFileApplicationListener

@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());
		}
	}
	//postProcessors 
	//0 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor@2302} 
	//1 = {SpringApplicationJsonEnvironmentPostProcessor@2303} 
	//3 = {ConfigFileApplicationListener@2296} 
	//2 = {CloudFoundryVcapEnvironmentPostProcessor@2304} 
	//4 = {DebugAgentEnvironmentPostProcessor@2305} 

		//ConfigFileApplicationListener
		postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication());
	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application)   {
		addPropertySources(environment, application.getResourceLoader());
	}
	
	protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
		RandomValuePropertySource.addToEnvironment(environment);
		new Loader(environment, resourceLoader).load();
	}
	
	//1.向配置源中加入 RandomValuePropertySource {name='random'}
	public static void addToEnvironment(ConfigurableEnvironment environment) {
		environment.getPropertySources().addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
				new RandomValuePropertySource(RANDOM_PROPERTY_SOURCE_NAME));
		logger.trace("RandomValuePropertySource add to Environment");
	}
	
	//2. new Loader(environment, resourceLoader).load(); 
	//配置文件路径	private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/";
	//载入配置文件applicationConfig 也就是application.properties 和 application-{profile}.properties
	
	void load() {
				FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
						(defaultProperties) -> {
							this.profiles = new LinkedList<>();
							this.processedProfiles = new LinkedList<>();
							this.activatedProfiles = false;
							this.loaded = new LinkedHashMap<>();
							initializeProfiles();
							while (!this.profiles.isEmpty()) {
								Profile profile = this.profiles.poll();
								if (isDefaultProfile(profile)) {
									addProfileToEnvironment(profile.getName());
								}
								load(profile, this::getPositiveProfileFilter,
										addToLoaded(MutablePropertySources::addLast, false));
								this.processedProfiles.add(profile);
							}
							load(null, this::getNegativeProfileFilter, addToLoaded(MutablePropertySources::addFirst, true));
							addLoadedPropertySources();
							applyActiveProfiles(defaultProperties);
						});
			}

5 = {RandomValuePropertySource@2986} "RandomValuePropertySource {name='random'}" 
6 = {OriginTrackedMapPropertySource@2987} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application-prod.properties]'}" 
7 = {OriginTrackedMapPropertySource@2988} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}"

5.bindToSpringApplication

把环境中的spring.main.*绑定到 SpringApplication中

	protected void bindToSpringApplication(ConfigurableEnvironment environment) {
		try {
			Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
		}
		catch (Exception ex) {
			throw new IllegalStateException("Cannot bind to SpringApplication", ex);
		}
	}

比如: banner-mode默认是CONSOLE在这里插入图片描述

然后我们比如设置 banner-mode为off 不输出
在这里插入图片描述
在这里插入图片描述
这样 banner就不会输出了.

6.项目环境转换

环境对的上就不转了,对不上新建一个
然后又走一下ConfigurationPropertySources.attach(environment);就是移除了重新设置

	if (!this.isCustomEnvironment) {
		environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
				deduceEnvironmentClass());
	}
	
	StandardEnvironment convertEnvironmentIfNecessary(ConfigurableEnvironment environment,
			Class<? extends StandardEnvironment> type) {
		if (type.equals(environment.getClass())) {
		//类型对的上 还是原来的
			return (StandardEnvironment) environment;
		}
		return convertEnvironment(environment, type);
	}

到此环境初始化操作完成了.

最后

PropertySource:

0 = {ConfigurationPropertySourcesPropertySource@3037} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
1 = {PropertySource$StubPropertySource@2131} "StubPropertySource {name='servletConfigInitParams'}"
2 = {PropertySource$StubPropertySource@2132} "StubPropertySource {name='servletContextInitParams'}"
3 = {PropertiesPropertySource@2133} "PropertiesPropertySource {name='systemProperties'}"
4 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@2985} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
5 = {RandomValuePropertySource@2986} "RandomValuePropertySource {name='random'}"
6 = {OriginTrackedMapPropertySource@2987} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application-prod.properties]'}"
7 = {OriginTrackedMapPropertySource@2988} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}"

配置顺序就是上到下,上面优先于下面.
我有些没有设置所以配置源是这些, 下面是官方文档介绍的外部化配置
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值