SpringBoot启动自动加载自定义模块的yml文件(PropertySourceFactory)

本文介绍了如何通过自定义YamlPropertySourceFactory实现Spring配置加载的灵活性提升,避免了传统方式的限制。步骤包括:1. 创建实现PropertySourceFactory的YamlPropertySourceFactory;2. 使用YamlPropertiesFactoryBean从资源流加载Properties;3. 将Properties转化为PropertySource并添加到Spring。只需在@Configuration类中使用@PropertySource指定配置文件路径即可。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://deinum.biz/2018-07-04-PropertySource-with-yaml-files/

背景

  • 自定义模块时经常会编写当前模块的一些核心yml配置,如果要被Spring容器加载到通常的做法是将自定义模块的yml命名为application-模块名.yml,比如db模块命名为application-db.yml,然后再在spring.profiles.include中引入该db,即可加载到子模块配置(前提是maven构建时能够将resources资源目录编译进去)。
  • 上面说的这种限制有很多,子模块对于父模块是黑箱操作,我们无法得知有多少个子模块要被include进来,而且前缀必须以application开头。

今天我们来看另外一种更加灵活的方式,自定义名称的yml直接在子模块中加载,各位朋友继续往下看PropertySourceFactory如何实现。

总结3步走:

  • 定义一个YamlPropertySourceFactory,实现PropertySourceFactory,重写createPropertySource方法

  • 将接口给过来的资源流文件使用加载到spring提供的YmlPropertiesFactorBean中,由该工厂Bean产出一个Properties对象

  • 将生成的Properties对象传入PropertiesPropertySource中产出一个PropertySource对象

    import lombok.AllArgsConstructor;
    import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
    import org.springframework.core.env.PropertiesPropertySource;
    import org.springframework.core.env.PropertySource;
    import org.springframework.core.io.support.EncodedResource;
    import org.springframework.core.io.support.PropertySourceFactory;
    
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.Properties;
    
    /**
     * @description:
     * @author: jianjun.ren
     * @date: Created in 2020/9/24 12:05
     */
    @AllArgsConstructor
    public class YamlPropertySourceFactory implements PropertySourceFactory {
    	//这个方法有2个入参,分别为资源名称和资源对象,这是第一步
        public PropertySource< ? > createPropertySource(String name, EncodedResource resource) throws IOException {
        
        	//这是第二步,根据流对象产出Properties对象
            Properties propertiesFromYaml = loadYamlIntoProperties(resource);
            String sourceName = name != null ? name : resource.getResource().getFilename();
            assert sourceName != null;
            
            //这是第三部,根据Properties对象,产出PropertySource对象,放入到Spring中
            return new PropertiesPropertySource(sourceName, propertiesFromYaml);
        }
    
        private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException {
            try {
                YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
                factory.setResources(resource.getResource());
                factory.afterPropertiesSet();
                return factory.getObject();
            } catch (IllegalStateException e) {
                Throwable cause = e.getCause();
                if (cause instanceof FileNotFoundException) {
                    throw (FileNotFoundException) e.getCause();
                }
                throw e;
            }
        }
    }
    

创建咱们是说完了,小伙伴有很多问号,怎么去使用呢?接下来我们再看康康

  • 在任意一个@Configuration类中,你自己写一个也可以,反正能够被Spring所扫描的
  • 加入下面这段代码,其实就一行
    @Configuration
    //这个地方的YamlPropertySourceFactory就是上面编写的代码类
    @PropertySource(factory = YamlPropertySourceFactory.class, value = "classpath:xxx-xxx.yml")
    public class XXXXConfiguration {
    		
    }
    

好了到这里就结束了,去使用看看效果吧~

### Spring Boot 中读取外部 YAML 文件的方法 #### 使用 `@PropertySource` 注解配合 `YamlPropertySourceFactory` 为了使应用程序能够从外部位置加载 `.yml` 配置文件,在启动类或其他配置类上可以使用 `@PropertySource` 注解,并指定自定义的 `YamlPropertySourceFactory` 来处理 YAML 文件。这允许程序灵活地指向任意路径下的配置文件。 ```java @Configuration public class AppConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() { return new PropertySourcesPlaceholderConfigurer(); } @Bean public YamlPropertySourceLoader yamlPropertySourceLoader(){ return new YamlPropertySourceLoader(); } } ``` 对于上述代码片段,还需要创建一个工厂类实现 `PropertySourceFactory` 接口以便正确解析 YAML 文件[^1]: ```java import org.springframework.core.io.support.DefaultPropertySourceFactory; import org.springframework.core.io.support.EncodedResource; import java.util.List; import java.util.Map; public class YamlPropertySourceFactory extends DefaultPropertySourceFactory { @Override protected Object createPropertySource(String name, EncodedResource resource) throws IOException { List<org.yaml.snakeyaml.Yaml> list = loadYamls(resource); Map<String,Object> sourceMap = (Map)((List<Map>)list.get(0)).get(0); return new Properties(name,sourceMap); } private List<org.yaml.snakeyaml.Yaml> loadYamls(EncodedResource encodedResource)throws FileNotFoundException{ try(InputStream inputStream=encodedResource.getInputStream()){ Yaml yaml=new Yaml(new Constructor(Map.class)); return yaml.loadAll(inputStream); } } } ``` 接着可以在需要的地方注入相应的属性值,比如通过 `@Value("${property.key}")` 或者利用 `@ConfigurationProperties` 绑定整个对象到特定前缀下的一组配置项[^3]。 当涉及到更复杂的场景时,如多环境部署或多模块共享同一套基础配置的情况下,则推荐采用第二种更为简洁高效的方式——即直接在 `application.yml` 中声明外部资源的位置并启用它作为默认配置源之一[^2]。 #### 利用命令行参数或系统变量覆盖内部配置 除了硬编码设定外,还可以借助 JVM 启动选项 `-Dspring.config.location=file:/path/to/your/application.yml` 动态改变配置文件所在目录;这种方式特别适用于容器化环境中传递敏感信息而不必将其暴露于版本控制系统内[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君哥聊编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值