入口
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
斷點跟蹤
1.準備環境
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 創建和配置環境
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (this.webApplicationType == WebApplicationType.NONE) {
environment = new EnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
2.創建和配置環境
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
if (this.webApplicationType == WebApplicationType.SERVLET) {
return new StandardServletEnvironment();
}
return new StandardEnvironment();
}
返回值屬性
配置環境
protected void configureEnvironment(ConfigurableEnvironment environment,
String[] args) {
// 配置property源
configurePropertySources(environment, args);
// 配置profiles
configureProfiles(environment, args);
}
//配置文件什麼都不寫默認情況,此方法不會做任何操作
protected void configurePropertySources(ConfigurableEnvironment environment,
String[] args) {
MutablePropertySources sources = environment.getPropertySources();
if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
sources.addLast(
new MapPropertySource("defaultProperties", this.defaultProperties));
}
省略。。。。。。
}
//爲整個application配置活躍的環境
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
// 確保初始化環境
environment.getActiveProfiles();
Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
// 賦值
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}
看上面的getActiveProfiles方法,獲取activiti的屬性值
// 獲取activit的profiles 比如spring.profiles.activite = dev
protected Set<String> doGetActiveProfiles() {
// 同步activeProfiles
synchronized (this.activeProfiles) {
//判空操作
if (this.activeProfiles.isEmpty()) {
// get spring.profiles.active屬性的值
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
// 是否有值
if (StringUtils.hasText(profiles)) {
setActiveProfiles(StringUtils.commaDelimitedListToStringArray(
StringUtils.trimAllWhitespace(profiles)));
}
}
return this.activeProfiles;
}
}
//把activit的屬性值 賦給ConfigurableEnvironment
public void setActiveProfiles(String... profiles) {
Assert.notNull(profiles, "Profile array must not be null");
synchronized (this.activeProfiles) {
this.activeProfiles.clear();
for (String profile : profiles) {
validateProfile(profile);
this.activeProfiles.add(profile);
}
}
}
給listeners添加當前的environmen
public void environmentPrepared(ConfigurableEnvironment environment) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.environmentPrepared(environment);
}
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
this.application, this.args, environment));
}
@Override
public void multicastEvent(ApplicationEvent event) {
// 組播事件
multicastEvent(event, resolveDefaultEventType(event));
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
// 重點方法 調用監聽器監聽事件
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
// 同上
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 重點 這方法會調用ConfigFileApplicationListener中的方法
listener.onApplicationEvent(event);
}
省略。。。。。。
}
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
省略。。。。。。
}
for (EnvironmentPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessEnvironment(event.getEnvironment(),
event.getSpringApplication());
}
加載Yml配置文件中的profiles的屬性關鍵點,在中的addPropertySources方法,這個方法中會有一個load的操作
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
addPropertySources(environment, application.getResourceLoader());
}
new Loader(environment, resourceLoader).load();
load中調用一個初始化的方法,看到圖中各個參數的值,第一調用會獲取上文中的默認的屬性值default。
public void load() {
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();
// 加載①
load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
}
load(null, this::getNegativeProfileFilter,
addToLoaded(MutablePropertySources::addFirst, true));
addLoadedPropertySources();
}
上面①的調用會經過下面這個流程,主要方法都加粗顯示
private void load(Profile profile, DocumentFilterFactory filterFactory,
DocumentConsumer consumer) {
getSearchLocations().forEach((location) -> {
boolean isFolder = location.endsWith("/");
Set<String> names = (isFolder ? getSearchNames() : NO_SEARCH_NAMES);
names.forEach(
(name) -> load(location, name, profile, filterFactory, consumer));
});
}
private void load(String location, String name, Profile profile,
DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
省略。。。。。。
for (PropertySourceLoader loader : this.propertySourceLoaders) {
for (String fileExtension : loader.getFileExtensions()) {
String prefix = location + name;
fileExtension = "." + fileExtension;
loadForFileExtension(loader, prefix, fileExtension, profile,
filterFactory, consumer);
}
}
}
private void loadForFileExtension(PropertySourceLoader loader, String prefix,
String fileExtension, Profile profile,
DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
省略。。。。。。
// Also try the profile-specific section (if any) of the normal file
load(loader, prefix + fileExtension, profile, profileFilter, consumer);
}
private void load(PropertySourceLoader loader, String location, Profile profile,
DocumentFilter filter, DocumentConsumer consumer) {
try {
// 讀取文件
Resource resource = this.resourceLoader.getResource(location);
String description = getDescription(location, resource);
if (profile != null) {
description = description + " for profile " + profile;
}
// 如果讀取的文件不存在,直接return,從調用方法進行下一個文件循環
// 如果當前文件夾的文件都掃描完成,直接掃面下一個文件夾
if (resource == null || !resource.exists()) {
this.logger.trace("Skipped missing config " + description);
return;
}
if (!StringUtils.hasText(
StringUtils.getFilenameExtension(resource.getFilename()))) {
this.logger.trace("Skipped empty config extension " + description);
return;
}
String name = "applicationConfig: [" + location + "]";
List<Document> documents = loadDocuments(loader, name, resource);
if (CollectionUtils.isEmpty(documents)) {
this.logger.trace("Skipped unloaded config " + description);
return;
}
List<Document> loaded = new ArrayList<>();
for (Document document : documents) {
if (filter.match(document)) {
addActiveProfiles(document.getActiveProfiles());
addProfiles(document.getIncludeProfiles());
loaded.add(document);
}
}
Collections.reverse(loaded);
if (!loaded.isEmpty()) {
loaded.forEach((document) -> consumer.accept(profile, document));
this.logger.debug("Loaded config file " + description);
}
}
catch (Exception ex) {
throw new IllegalStateException("Failed to load property "
+ "source from location '" + location + "'", ex);
}
}
當讀取到dev的時候,會調用load中的這個循環,
for (Document document : documents) {
if (filter.match(document)) {
addActiveProfiles(document.getActiveProfiles());
addProfiles(document.getIncludeProfiles());
loaded.add(document);
}
}
void addActiveProfiles(Set<Profile> profiles) {
if (this.activatedProfiles || profiles.isEmpty()) {
return;
}
addProfiles(profiles);
this.logger.debug("Activated activeProfiles "
+ StringUtils.collectionToCommaDelimitedString(profiles));
this.activatedProfiles = true;
//移除未裝配的默認配置屬性,加載當前獲取的屬性
removeUnprocessedDefaultProfiles();
}
addProfiles調用addProfileToEnvironment方法,向當前的environment添加profiles。