目录
环境准备流程
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]'}"
配置顺序就是上到下,上面优先于下面.
我有些没有设置所以配置源是这些, 下面是官方文档介绍的外部化配置