深入理解SpringBoot(二) 加载配置文件

下面我们来说一下SpringBoot是怎么加载配置文件的。我们先来看一下SpringApplication的setInitializers方法

public void setInitializers(
        Collection<? extends ApplicationContextInitializer<?>> initializers) {
    this.initializers = new ArrayList<>();
    this.initializers.addAll(initializers);
}

然后再看一下ConfigFileApplicationContextInitializer这个类

public void initialize(ConfigurableApplicationContext applicationContext) {
    new ConfigFileApplicationListener() {
        public void apply() {
            addPropertySources(applicationContext.getEnvironment(),
                    applicationContext);
            addPostProcessors(applicationContext);
        }
    }.apply();
}

再看一下ConfigFileApplicationListener这个类

  public void postProcessEnvironment(ConfigurableEnvironment environment,
        SpringApplication application) {
    addPropertySources(environment, application.getResourceLoader());
}

加载PropertySource,就是配置文件

protected void addPropertySources(ConfigurableEnvironment environment,
        ResourceLoader resourceLoader) {
    RandomValuePropertySource.addToEnvironment(environment);
    new Loader(environment, resourceLoader).load();
}

再到load方法

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();
            if (profile != null && !profile.isDefaultProfile()) {
                addProfileToEnvironment(profile.getName());
            }
            load(profile, this::getPositiveProfileFilter,
                    addToLoaded(MutablePropertySources::addLast, false));
            this.processedProfiles.add(profile);
        }
        resetEnvironmentProfiles(this.processedProfiles);
        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) {
        if (!StringUtils.hasText(name)) {
            for (PropertySourceLoader loader : this.propertySourceLoaders) {
                if (canLoadFileExtension(loader, location)) {
                    load(loader, location, profile,
                            filterFactory.getDocumentFilter(profile), consumer);
                    return;
                }
            }
        }
        Set<String> processed = new HashSet<>();
        for (PropertySourceLoader loader : this.propertySourceLoaders) {
            for (String fileExtension : loader.getFileExtensions()) {
                if (processed.add(fileExtension)) {
                    loadForFileExtension(loader, location + name, "." + fileExtension,
                            profile, filterFactory, consumer);
                }
            }
        }
    }

调用PropertySourceLoader来加载配置文件
看一下PropertiesPropertySourceLoader这个类

public List<PropertySource<?>> load(String name, Resource resource)
        throws IOException {
    Map<String, ?> properties = loadProperties(resource);
    if (properties.isEmpty()) {
        return Collections.emptyList();
    }
    return Collections
            .singletonList(new OriginTrackedMapPropertySource(name, properties));
}

再到loadProperties方法

private Map<String, ?> loadProperties(Resource resource) throws IOException {
    String filename = resource.getFilename();
    if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
        return (Map) PropertiesLoaderUtils.loadProperties(resource);
    }
    return new OriginTrackedPropertiesLoader(resource).load();
}

把properties配置文件加载进来,放到map里返回
那么我们一般默认的配置文件是application.properties,这个是在哪里配置的呢,我们来看一下ConfigFileApplicationListener有一个属性值DEFAULT_NAMES

private static final String DEFAULT_NAMES = "application";

在getSearchNames方法里添加进去

private Set<String> getSearchNames() {
        if (this.environment.containsProperty(CONFIG_NAME_PROPERTY)) {
            String property = this.environment.getProperty(CONFIG_NAME_PROPERTY);
            return asResolvedSet(property, null);
        }
        return asResolvedSet(ConfigFileApplicationListener.this.names, DEFAULT_NAMES);
    }

SpringBoot的加载配置文件的过程就分析到这里了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容