[springboot源码分析]-启动-02-prepareEnvironment

org.springframework.core.env.Environment 类图
在这里插入图片描述

0.prepareEnvironment

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// 1. Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		
		//2.
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		
		//3. environmentPrepared: 加载spring.config...
		listeners.environmentPrepared(bootstrapContext, environment);
		
		//确保defaultProperties优先级最低
		DefaultPropertiesPropertySource.moveToEnd(environment);
		Assert.state(!environment.containsProperty("spring.main.environment-prefix"),"Environment prefix cannot be set via properties.");
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
			environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
		}
		//略...
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

1. getOrCreateEnvironment() : ApplicationServletEnvironment

see: AnnotationConfigServletWebServerApplicationContext.Factory.createEnvironment()

public interface Environment extends PropertyResolver {
	String[] getActiveProfiles();
}

public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
}


public abstract class AbstractEnvironment implements ConfigurableEnvironment {

	public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore";
	public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";
	public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";
	protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default";


	private final MutablePropertySources propertySources;
	public AbstractEnvironment() {
		this(new MutablePropertySources());
	}


}

public class StandardEnvironment extends AbstractEnvironment {
	public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
	public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";

	protected StandardEnvironment(MutablePropertySources propertySources) {
		super(propertySources);
	}


	@Override
	protected void customizePropertySources(MutablePropertySources propertySources) {
		propertySources.addLast( new PropertiesPropertySource("systemProperties", getSystemProperties())); //优先级4
		propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", getSystemEnvironment()));//优先级5
	}
}


public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {

    private static final boolean jndiPresent = ClassUtils.isPresent("javax.naming.InitialContext", StandardServletEnvironment.class.getClassLoader());

    public StandardServletEnvironment() {
    }

    protected StandardServletEnvironment(MutablePropertySources propertySources) {
        super(propertySources);
    }

    protected void customizePropertySources(MutablePropertySources propertySources) {
        propertySources.addLast(new PropertySource.StubPropertySource("servletConfigInitParams")); //优先级1
        propertySources.addLast(new PropertySource.StubPropertySource("servletContextInitParams"));//优先级2
        if (jndiPresent && JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
            propertySources.addLast(new JndiPropertySource("jndiProperties"));//优先级3
        }

        super.customizePropertySources(propertySources);//parent
    }

    public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
        WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
    }
}

class ApplicationServletEnvironment extends StandardServletEnvironment {
}

MutablePropertySources

public class MutablePropertySources implements PropertySources {
	private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<>();
}

1.1 配置文件优先级

此阶段之后,MutablePropertySources存在如下PropertySource:

  1. servletConfigInitParams
  2. servletContextInitParams
  3. jndiProperties
  4. systemProperties
  5. systemEnvironment

springboot-配置文件优先级

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

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
	if (this.addConversionService) {
		//ConversionService
		environment.setConversionService(new ApplicationConversionService());
	}
	//2.1
	configurePropertySources(environment, args);

	//2.2 空实现
	configureProfiles(environment, args);
}

//2.1
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
	MutablePropertySources sources = environment.getPropertySources();
	if (!CollectionUtils.isEmpty(this.defaultProperties)) {
		//最终会调用: sources.addLast(propertySource);  //  defaultProperties 优先级最低
		DefaultPropertiesPropertySource.addOrMerge(this.defaultProperties, sources);
	}
	if (this.addCommandLineProperties && args.length > 0) {
		String name = "commandLineArgs";
		if (sources.contains(name)) {
			PropertySource<?> source = sources.get(name);
			CompositePropertySource composite = new CompositePropertySource(name);
			composite
				.addPropertySource(new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
			composite.addPropertySource(source);
			sources.replace(name, composite);
		}
		else {
			//commandline args 优先级最高 : 
			sources.addFirst(new SimpleCommandLinePropertySource(args));
		}
	}
}

2.1 配置文件优先级

  1. CommandLinePropertySource
  2. servletConfigInitParams
  3. servletContextInitParams
  4. jndiProperties
  5. systemProperties
  6. systemEnvironment
  7. defaultPropertiesSource

3. listeners.environmentPrepared(bootstrapContext, environment);

3.1 EnvironmentPostProcessorApplicationListener.environmentPrepared()


//1.
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
	public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
			ConfigurableEnvironment environment) {

		/**
		 * ====spring.factories===
		 org.springframework.context.ApplicationListener=\
			org.springframework.boot.ClearCachesApplicationListener,\
			org.springframework.boot.builder.ParentContextCloserApplicationListener,\
			org.springframework.boot.context.FileEncodingApplicationListener,\
			org.springframework.boot.context.config.AnsiOutputApplicationListener,\
			org.springframework.boot.context.config.DelegatingApplicationListener,\
			org.springframework.boot.context.logging.LoggingApplicationListener,\
			org.springframework.boot.env.EnvironmentPostProcessorApplicationListener - 2
		 */
		this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
				
	}
}

//2
public class EnvironmentPostProcessorApplicationListener implements SmartApplicationListener, Ordered {

	private final Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory;

	//2.1
	public EnvironmentPostProcessorApplicationListener() {
		/**
		 * 加载spring.factories load EnvironmentPostProcessor
		 * return new ReflectionEnvironmentPostProcessorsFactory(classLoader,SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));
		 */ 
		this(EnvironmentPostProcessorsFactory::fromSpringFactories, new DeferredLogs());
	}

	//2.2
	public EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory) {
		this((classloader) -> postProcessorsFactory, new DeferredLogs());
	}

	//2.3
	EnvironmentPostProcessorApplicationListener(
			Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory, DeferredLogs deferredLogs) {
		this.postProcessorsFactory = postProcessorsFactory;
		this.deferredLogs = deferredLogs;
	}

	
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		//2.4
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
		}
		//略....
	}

	private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
		ConfigurableEnvironment environment = event.getEnvironment();
		SpringApplication application = event.getSpringApplication();
		//2.5. 通过postProcessorsFactory 获取EnvironmentPostProcessor -->  加载spring.factories load EnvironmentPostProcessor
		for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),event.getBootstrapContext())) {
				
			//2.6. for-each 执行 postProcessEnvironment
			postProcessor.postProcessEnvironment(environment, application);
		}
	}
}

3.2 spring.factories: EnvironmentPostProcessor

org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor

优先级

public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
	private static final String VCAP_APPLICATION = "VCAP_APPLICATION";
	private static final String VCAP_SERVICES = "VCAP_SERVICES";
	private int order = ConfigDataEnvironmentPostProcessor.ORDER - 1;
}

public class RandomValuePropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
	public static final int ORDER = Ordered.HIGHEST_PRECEDENCE + 1;
}


public class SystemEnvironmentPropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {

	public static final int DEFAULT_ORDER = SpringApplicationJsonEnvironmentPostProcessor.DEFAULT_ORDER - 1; // ==== Ordered.HIGHEST_PRECEDENCE + 4

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		String sourceName = "systemEnvironment";
		PropertySource<?> propertySource = environment.getPropertySources().get(sourceName);
		if (propertySource != null) {
			replacePropertySource(environment, sourceName, propertySource, application.getEnvironmentPrefix());
		}
	}
}

public class SpringApplicationJsonEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
	public static final String SPRING_APPLICATION_JSON_PROPERTY = "spring.application.json";
	public static final String SPRING_APPLICATION_JSON_ENVIRONMENT_VARIABLE = "SPRING_APPLICATION_JSON";
	private static final String SERVLET_ENVIRONMENT_CLASS = "org.springframework.web." + "context.support.StandardServletEnvironment";
			
	private static final Set<String> SERVLET_ENVIRONMENT_PROPERTY_SOURCES = new LinkedHashSet<>(
			Arrays.asList(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME,
					StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME,
					StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME));


	public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 5;
}

public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
	public static final int ORDER = Ordered.HIGHEST_PRECEDENCE + 10;
}

public class DebugAgentEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
	private static final String REACTOR_DEBUGAGENT_CLASS = "reactor.tools.agent.ReactorDebugAgent";
	private static final String DEBUGAGENT_ENABLED_CONFIG_KEY = "spring.reactor.debug-agent.enabled";

	@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE;
	}

}

3.3 ConfigDataEnvironmentPostProcessor.postProcessEnvironment()

public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		//获取additionalProfiles
		postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
	}

	void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
			Collection<String> additionalProfiles) {
		resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
		//1.getConfigDataEnvironment()
		//2.ConfigDataEnvironment.processAndApply();
		getConfigDataEnvironment(environment, resourceLoader, additionalProfiles).processAndApply();
	}

	ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
			Collection<String> additionalProfiles) {
		//1
		return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader,additionalProfiles, this.environmentUpdateListener);
	}

}

3.3.1 new ConfigDataEnvironment()

class ConfigDataEnvironment {

	static final String LOCATION_PROPERTY = "spring.config.location";
	static final String ADDITIONAL_LOCATION_PROPERTY = "spring.config.additional-location";
	static final String IMPORT_PROPERTY = "spring.config.import";
	static final String ON_NOT_FOUND_PROPERTY = "spring.config.on-not-found";
	static final ConfigDataLocation[] DEFAULT_SEARCH_LOCATIONS;
	static {
		List<ConfigDataLocation> locations = new ArrayList<>();
		locations.add(ConfigDataLocation.of("optional:classpath:/;optional:classpath:/config/"));
		locations.add(ConfigDataLocation.of("optional:file:./;optional:file:./config/;optional:file:./config/*/"));
		DEFAULT_SEARCH_LOCATIONS = locations.toArray(new ConfigDataLocation[0]);
	}

	//1
	ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
			ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
			ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
		Binder binder = Binder.get(environment);
		UseLegacyConfigProcessingException.throwIfRequested(binder);
		this.logFactory = logFactory;
		this.logger = logFactory.getLog(getClass());
		this.notFoundAction = binder.bind(ON_NOT_FOUND_PROPERTY, ConfigDataNotFoundAction.class)
			.orElse(ConfigDataNotFoundAction.FAIL);
		this.bootstrapContext = bootstrapContext;
		this.environment = environment;
		this.resolvers = createConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader);
		this.additionalProfiles = additionalProfiles;
		this.environmentUpdateListener = (environmentUpdateListener != null) ? environmentUpdateListener
				: ConfigDataEnvironmentUpdateListener.NONE;
		this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext, resourceLoader.getClassLoader());
		this.contributors = createContributors(binder); // 从spring的各个目录加载配置文件, build contributors 略....
	}
}	

3.3.2 ConfigDataEnvironment.processAndApply();

class ConfigDataEnvironment {
	//2
	void processAndApply() {
		ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, this.notFoundAction, this.resolvers,
				this.loaders);
		registerBootstrapBinder(this.contributors, null, DENY_INACTIVE_BINDING);
		ConfigDataEnvironmentContributors contributors = processInitial(this.contributors, importer);
		ConfigDataActivationContext activationContext = createActivationContext(
				contributors.getBinder(null, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
		contributors = processWithoutProfiles(contributors, importer, activationContext); //2.1 without profile
		activationContext = withProfiles(contributors, activationContext);
		contributors = processWithProfiles(contributors, importer, activationContext);  //2.2 with profile

		//2.3  applyToEnvironment
		applyToEnvironment(contributors, activationContext, importer.getLoadedLocations(),importer.getOptionalLocations()); 
	}


	//2.3
	private void applyToEnvironment(ConfigDataEnvironmentContributors contributors,
			ConfigDataActivationContext activationContext, Set<ConfigDataLocation> loadedLocations,
			Set<ConfigDataLocation> optionalLocations) {
		checkForInvalidProperties(contributors);
		checkMandatoryLocations(contributors, activationContext, loadedLocations, optionalLocations);
		MutablePropertySources propertySources = this.environment.getPropertySources();
		 //2.3.1
		applyContributor(contributors, activationContext, propertySources); 
		DefaultPropertiesPropertySource.moveToEnd(propertySources); //依旧确保default properties 优先级最低
		Profiles profiles = activationContext.getProfiles();
		this.environment.setDefaultProfiles(StringUtils.toStringArray(profiles.getDefault()));
		this.environment.setActiveProfiles(StringUtils.toStringArray(profiles.getActive()));
		this.environmentUpdateListener.onSetProfiles(profiles);
	}

	//2.3.1
	private void applyContributor(ConfigDataEnvironmentContributors contributors,
			ConfigDataActivationContext activationContext, MutablePropertySources propertySources) {
		for (ConfigDataEnvironmentContributor contributor : contributors) {
			PropertySource<?> propertySource = contributor.getPropertySource();
			if (contributor.getKind() == ConfigDataEnvironmentContributor.Kind.BOUND_IMPORT && propertySource != null) {
				if (!contributor.isActive(activationContext)) {
					//若active 不匹配,则跳过
					this.logger.trace(LogMessage.format("Skipping inactive property source '%s'", propertySource.getName()));
				}
				else {
					propertySources.addLast(propertySource); //优先级最低....
					this.environmentUpdateListener.onPropertySourceAdded(propertySource, contributor.getLocation(),contributor.getResource());
				}
			}
		}
	}
}

3.4 配置文件优先级

  1. CommandLinePropertySource
  2. servletConfigInitParams
  3. servletContextInitParams
  4. jndiProperties
  5. systemProperties
  6. systemEnvironment
  7. spring.config
    • CloudFoundryVcapEnvironmentPostProcessor
    • RandomValuePropertySourceEnvironmentPostProcessor
    • SystemEnvironmentPropertySourceEnvironmentPostProcessor
    • SpringApplicationJsonEnvironmentPostProcessor
    • ConfigDataEnvironmentPostProcessor
    • DebugAgentEnvironmentPostProcessor
  8. defaultPropertiesSource
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值