代码之家  ›  专栏  ›  技术社区  ›  Héctor

从application.yml读取属性时,将忽略弹簧配置文件

  •  3
  • Héctor  · 技术社区  · 7 年前

    我有一个扫描Spring上下文的代码:

    public void scan() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    
        context.register(SomeConfig.class);
        context.refresh();
    }
    

    我需要从中读取属性 application.yml SomeConfig 同学们,我有这个:

    @Configuration
    @PropertySource(value = "classpath:application.yml", factory = YamlPropertyLoaderFactory.class)
    public class SomeConfig {
      //some beans
    }
    

    here )

    是一个典型的Spring引导文件,具有按配置文件列出的某些属性和默认配置文件:

    spring:
      profiles:
        active: p1
    
    ---
    
    spring:
       profiles: p1
    
    file: file1.txt
    
    ---
    
    spring:
       profiles: p2
    
    file: file2.txt
    

    file 财产使用 @Value

    当我运行我的应用程序,我通过 -Dspring.profiles.active=p1 变量,但我得到一个错误:

    无法解析值“${file}”中的占位符“file”

    (由于application.yml的默认概要文件设置为p1,所以即使我没有传递任何概要文件,它也应该可以工作)

    file: file1.txt
    

    所以,这意味着上下文扫描没有读取profile变量。

    另外,如果我以“编程方式”设置活动配置文件,它也不会解析属性:

    context.getEnvironment().setActiveProfiles("p1");
    
    2 回复  |  直到 7 年前
        1
  •  5
  •   pcoates    7 年前

    这个 YamlPropertyLoaderFactory 您所指的具有以下代码:

    public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            if (resource == null){
                return super.createPropertySource(name, resource);
            }
    
            return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), null);
        }
    }
    

    第三个参数 YamlPropertySourceLoader.load() 方法实际上是要为其设置属性的配置文件名称。当这个示例传入null时,它只返回yml文件中的属性集,而不是特定概要文件的属性集。

    spring:
      profiles:
        active: p1
    
    ---
    

    我不认为这是很容易拿起的活动配置文件名称在 YamlPropertyLoader工厂 ,尽管你可以尝试像。。。

    public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            if (resource == null){
                return super.createPropertySource(name, resource);
            }
    
            String activeProfile = System.getProperty("spring.profiles.active");
            return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), activeProfile);
        }
    }
    

    或者,当您在yml文件中有活动的概要文件名时,您可以调用 YamlPropertySourceLoader().load 使用null获取spring.profiles.active属性,然后再次调用它以加载所需yml文件的实际部分。

    public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            if (resource == null){
                return super.createPropertySource(name, resource);
            }
            PropertySource<?> source = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), null);
            String activeProfile = source.getProperty("spring.profiles.active");
            return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), activeProfile);
        }
    }
    

    YamlPropertySourceLoader 是在2018年2月更改的( YamlPropertySourceLoader blame view in Git repo ). 它现在返回propertySource的列表,并且在load方法上没有第三个参数。

    如果您在yml文件中有spring.profiles.active属性,那么您就可以在更新版本的 YamlPropertySourceLoader公司

    public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
    
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            if (resource == null){
                return super.createPropertySource(name, resource);
            }
            List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
            for (PropertySource<?> checkSource : sources) {
                if (checkSource.containsProperty("spring.profiles.active")) {
                    String activeProfile = (String) checkSource.getProperty("spring.profiles.active");
                    for (PropertySource<?> source : sources) {
                        if (activeProfile.trim().equals(source.getProperty("spring.profiles"))) {
                            return source; 
                        }
                    }
                }
            }
            return sources.get(0);
        }
    
    }
    
        2
  •  0
  •   sulthan    6 年前

    @我尝试使用更新版本的YamlPropertySourceLoader加载配置文件时仍然失败。

    if (checkSource.containsProperty("spring.profiles.active"))

      profiles: dev
      excelPath :  /data/excel
      excecutionPath: http://localhost:8080/server/execute
      memberIP: localhost
      profilerPortNum: 3031
    
    --- 
    
    spring:
      profiles: uat
      excelPath :  /data/uat/excel
      excecutionPath: http://localhost:8080/server/execute
      memberIP: localhost
      profilerPortNum: 3032```
    
    @Configuration
    @PropertySource(value = "classpath:application.yml", factory = YamlPropertyLoaderFactory.class)
    public class ReadYamlProperties {
    }
    
    
    
        3
  •  -1
  •   user10527814 user10527814    7 年前

    要仅为特定轮廓设置特性,正确的缩进为:

    spring:
       profiles: p1
       file: file1.txt
    

    在上述情况下,您可以访问 file1.txt 具有 ${spring.file}