SpringBoot 2.0 系列004 --启动实战之配置文件

本文介绍了SpringBoot 2.0配置文件的加载流程和使用方法,包括如何使用非默认名称的配置文件以及如何加载外部配置文件进行统一管理。详细解释了通过设置`spring.config.name`和`spring.profiles.default`属性来改变默认配置,并提供了具体的配置示例和启动日志,便于读者实践操作。
摘要由CSDN通过智能技术生成

SpringBoot 2.0 系列004 --启动实战之配置文件

配置文件

配置文件加载流程

很多文档包括官方文档说SB的默认配置文件是application开头的文件,那么是为什么呢?

  • 我们先看下流程图 

由上述流程我们发现,在执行SpringApplication的run方法中的prepareEnvironment子方法时,触发ConfigFileApplicationListener类中的 load方法,完成配置文件的加载

  • ConfigFileApplicationListener分析
public void load() {
     
  this.profiles = Collections.asLifoQueue(new LinkedList<Profile>());
  this.processedProfiles = new LinkedList<>();
  this.activatedProfiles = false;
  this.loaded = new LinkedHashMap<>();
  // 核心初始化方法  负责初始化 profile (spring.profiles.active) 
  // 如果没有则使用默认的AbstractEnvironment类中的(spring.profiles.default)default(可以是application-default名称的,也可以起不加)
  initializeProfiles();
  // 不为空时 循环加载  初始化了  理论上不会为空
  while (!this.profiles.isEmpty()) {
     
    Profile profile = this.profiles.poll();
    // 第二步 此方法加载 文件的前缀 active 以及后缀  和路径 
    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) {
    
            // getSearch 如果你配置了spring.config.location 路径  则使用此处路径
            // 否则是用默认的 ConfigFileApplicationListener.DEFAULT_SEARCH_LOCATIONS
            // 即 private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
			getSearchLocations().forEach((location) -> {
    
				boolean isFolder = location.endsWith("/");
				// getSearchNames 是你配置文件的名称 ,如果配置了spring.config.name 则使用配置的这个名字
				// 否则使用默认的 private static final String DEFAULT_NAMES = "application";
				// 这就是默认是application这个名字的原因
				Set<String> names = (isFolder ? getSearchNames() : NO_SEARCH_NAMES);
				names.forEach(
				       
                        // 第三步  location是路径  name是文件名 profile则是-defalut部分或者其他-dev之类的
						(name) -> load(location, name, profile, filterFactory, consumer));
			});
		}
  • 接上边标注第三步
private void load(String location, String name, Profile profile,
				DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
    
    
            // 这里需要注意的是propertySourceLoaders 此处是在new loader的时候初始化的,即我们流程中的addPropertySources一步
               				        //底层使用的是META-INF/spring.factories
               				        /** org.springframework.boot.env.PropertySourceLoader=\
                                          org.springframework.boot.env.PropertiesPropertySourceLoader,\
                                          org.springframework.boot.env.YamlPropertySourceLoader
                                       */
           // 这也就是 文件后缀支持 yml,yaml,properties,xml的原因
           // 没有名字的情况
			if (!StringUtils.hasText(name)) {
    
				for (PropertySourceLoader loader : this.propertySourceLoaders) {
    
					if (canLoadFileExtension(loader, location)) {
    
						load(loader, location, profile,
								filterFactory.getDocumentFilter(profile), 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) {
    
			DocumentFilter defaultFilter = filterFactory.getDocumentFilter(null);
			DocumentFilter profileFilter = filterFactory.getDocumentFilter(profile);
			// 前边说的 -default和-dev部分
			if (profile != null) {
    
				// Try profile-specific file & profile section in profile file (gh-340)
				// prefix 是路径名+文件名
				// fileExtension是.yml这种
				// profile 则是第一步initializeProfiles 是this.profiles注入的
				String profileSpecificFile = prefix + "-" + profile + fileExtension;
				// 各处执行装载 扫描不同路径下是否有对应配置文件
				load(loader, profileSpecificFile, profile, defaultFilter, consumer);
				load(loader, profileSpecificFile, profile, profileFilter, consumer);
				// Try profile specific sections in files we've already processed
				for (Profile processedProfile : this.processedProfiles) {
    
					if (processedProfile != null) {
    
						String previouslyLoaded = prefix + "-" + processedProfile
								+ fileExtension;
						load(loader, previouslyLoaded, profile, profileFilter, 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;
				}
				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 + "]";
				// 转换成docment对象 
				List
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值