这些就是框架定义的,需要装配的类。
application.yml的加载
application.yml文件对于 Spring Boot 来说是核心配置文件,至关重要!那么,该文件是如何加载到内存的呢?我们需要从启动类的run()方法开始跟踪,该跟踪过程比较深,耐心差的读者慎入。
@SpringBootApplication
public class SpringbootSeniorApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootSeniorApplication.class, args);
}
}
进入run方法:
public class SpringApplication {
...
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public ConfigurableApplicationContext run(String... args) {
...
// 准备运行环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
...
}
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
...
// 让监听器监听环境准备过程
listeners.environmentPrepared(environment);
...
}
...
}
让监听器监听环境准备过程
class SpringApplicationRunListeners {
...
void environmentPrepared(ConfigurableEnvironment environment) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.environmentPrepared(environment);
}
}
...
}
发布环境准备事件
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
...
@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));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
// 触发监听器
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
...
}
触发监听器
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
...
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) {
...
listener.onApplicationEvent(event);
...
}
...
}
ApplicationListener#onApplicationEvent是一个接口方法,我们主要看它的ConfigFileApplicationListener实现类的实现
public class ConfigFileApplicationListener implements ... {
...
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) 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#postProcessEnvironment是一个接口方法,我们主要看它的ConfigFileApplicationListener实现类的实现
public class ConfigFileApplicationListener implements ... {
...
@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();
}
private class Loader {
void load() {
FilteredPropertySource.apply(
this.environment,
DEFAULT_PROPERTIES,
LOAD_FILTERED_PROPERTY,
(defaultProperties) -> {
...
while (!this.profiles.isEmpty()) {
...
load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false));
...
}
...
});
}
private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
getSearchLocations().forEach((location) -> {
boolean isDirectory = location.endsWith("/");
Set<String> names = isDirectory ? 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()) {
if (processed.add(fileExtension)) {
loadForFileExtension(loader, location + name, "." + fileExtension, profile, filterFactory, consumer);
}
}
}
}
private void loadForFileExtension(
PropertySourceLoader loader,
String prefix,
String fileExtension,
Profile profile,
DocumentFilterFactory filterFactory,
DocumentConsumer consumer) {
...
load(loader, prefix + fileExtension, profile, profileFilter, consumer);
}
private void load(
PropertySourceLoader loader,
String location,
Profile profile,
DocumentFilter filter,
DocumentConsumer consumer) {
...
List<Document> documents = loadDocuments(loader, name, resource);
...
}
private List<Document> loadDocuments(
PropertySourceLoader loader,
String name,
Resource resource) throws IOException {
DocumentsCacheKey cacheKey = new DocumentsCacheKey(loader, resource);
List<Document> documents = this.loadDocumentsCache.get(cacheKey);
if (documents == null) {
List<PropertySource<?>> loaded = loader.load(name, resource);
documents = asDocuments(loaded);
this.loadDocumentsCache.put(cacheKey, documents);
}
return documents;
}
}
...
}
PropertySourceLoader#getFileExtensions和PropertySourceLoader#load都是接口方法,我们主要看它的YamlPropertySourceLoader实现类的实现
public class YamlPropertySourceLoader implements PropertySourceLoader {
@Override
public String[] getFileExtensions() {
return new String[] { "yml", "yaml" };
}
@Override
public List<PropertySource<?>> load(
String name,
Resource resource) throws IOException {
...
return propertySources;
}
}
最后
感谢你看到这里,文章有什么不足还请指正,觉得文章对你有帮助的话记得给我点个赞!

评论列表