源码分析 1.找到配置文件
2.根据profile加载对应的文件或属性
3.把加载后的属性放到spring 容器中
spring boot项目的入口为main方法
加载配置的入口是有设计的。是观察者设计模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SpringApplication.run(SpringLogbackApplication.class , args);new SpringApplication(primarySources) setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class )); spring.factories ConfigFileApplicationListener public ConfigurableApplicationContext run (String... args )ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); listeners.environmentPrepared(environment); ConfigFileApplicationListener.onApplicationEvent(ApplicationEvent event ) private void onApplicationEnvironmentPreparedEvent (ApplicationEnvironmentPreparedEvent event )public void postProcessEnvironment (ConfigurableEnvironment environment, SpringApplication application )protected void addPropertySources (ConfigurableEnvironment environment, ResourceLoader resourceLoader )new Loader (environment, resourceLoader ).load () ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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); }); }
1 2 3 4 5 6 7 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)); }); }
这里涉及到3个值:去哪里找配置文件(location)、配置文件的名称是什么(getSearchNames)、不同环境(profile)
location位置: classpath:/, classpath:/config/, file:./, file:./config/ 优先级从低到高,最先加载file:./config/ 位置的配置文件;如果配置了spring.config.location属性则取这个属性的值。
配置文件的名字:默认值为:application;如果配置了spring.config.name属性则取改属性值。
环境为上面传进来的:自定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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 ; } } throw new IllegalStateException ("File extension of config file location '" + location + "' is not known to any PropertySourceLoader. If the location is meant to reference " + "a directory, it must end in '/'" ); } 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); } } } }
到这里就根据不同的文件名后缀来获取了。
所有的扩展名: properties xml yml yaml
参考 Application ConfigFileApplicationListener
https://blog.csdn.net/weixin_43732955/article/details/106600869
bootstrap BootstrapApplicationListener
https://baijiahao.baidu.com/s?id=1720638939882107917&wfr=spider&for=pc