让 @PropertySource 注解支持加载 yml 配置文件

本文发布于 2024年07月05日,阅读 29 次,点赞 0 次,归类于 Spring

by emanjusaka from https://www.emanjusaka.top/2024/07/annotation-@PropertySource-yml 彼岸花开可奈何

本文为原创文章,可能会更新知识点以及修正文中的一些错误,全文转载请保留原文地址,避免未即时修正的错误误导。

@PropertySource 默认只支持 properties 文件和 xml 文件,并不能加载 yml 或 yaml。我们可以通过自定义资源加载的工厂指定 yml 加载器去加载 yml 的配置文件。

@PropertySource

通过使用@PropertySource注解,可以在Spring应用程序中动态地加载属性文件,并将其中的属性注入到Bean中或其他需要使用属性值的地方。

 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Repeatable(PropertySources.class)
 public @interface PropertySource {
 ​
   /**
    * 指定属性源的名称。如果未指定,则根据属性文件的位置生成一个名称
    */
   String name() default "";
 ​
   /**
    * 指定属性文件的位置。支持 classpath 和文件路径,但不支持使用通配符,每个位置必须对应一
      * 个 .properties 文件。可以使用${...}占位符来引用已注册的属性源中的属性。
    */
   String[] value();
 ​
   /**
    * 指定当找不到属性文件时是否忽略错误。默认为false,即如果找不到属性文件,将抛出异常
    */
   boolean ignoreResourceNotFound() default false;
 ​
   /**
    * 指定属性文件的字符编码,默认为空。
    */
   String encoding() default "";
 ​
   /**
    * 指定一个自定义的PropertySourceFactory类,用于创建属性源。默认使用标准资源文件的默认        
      * 工厂。
    */
   Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
 ​
 }
  • @PropertySource默认对properties文件和 xml 文件可以进行加载,但对于yml或者yaml不能支持

实现对于yml的支持

  1. 新建YamlAndPropertySourceFactory类继承 DefaultPropertySourceFactory,然后重写 createPropertySource():

     package top.emanjusaka.properties.factory;
     ​
     import org.springframework.boot.env.YamlPropertySourceLoader;
     import org.springframework.core.env.PropertiesPropertySource;
     import org.springframework.core.env.PropertySource;
     import org.springframework.core.io.Resource;
     import org.springframework.core.io.support.DefaultPropertySourceFactory;
     import org.springframework.core.io.support.EncodedResource;
     ​
     import java.io.IOException;
     import java.util.List;
     import java.util.Properties;
     ​
     /**
      * @Author emanjusaka
      * @Date 2024/7/4 15:52
      * @Version 1.0
      */
     public class YamlAndPropertySourceFactory extends DefaultPropertySourceFactory {
         @Override
         public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
             if (resource == null) {
                 return super.createPropertySource(name, resource);
             }
             Resource res = resource.getResource();
             if (!res.exists()) {
                 return new PropertiesPropertySource(null, new Properties());
             } else if (res.getFilename().endsWith(".yml") || res.getFilename().endsWith(".yaml")) {
                 List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(res.getFilename(), res);
                 return sources.get(0);
             }
             return super.createPropertySource(name, resource);
         }
     }
  2. 使用时在@PropertySource注解中指定 factory 属性为上面自定义的工厂实现:

     package top.emanjusaka.properties;
     ​
     import lombok.Data;
     import org.springframework.boot.context.properties.ConfigurationProperties;
     import org.springframework.context.annotation.Configuration;
     import org.springframework.context.annotation.PropertySource;
     import top.emanjusaka.properties.factory.YamlAndPropertySourceFactory;
     ​
     /**
      * @Author emanjusaka
      * @Date 2024/7/4 15:49
      * @Version 1.0
      */
     @Configuration
     @PropertySource(value = "classpath:config/config.yml", factory = YamlAndPropertySourceFactory.class)
     @ConfigurationProperties(prefix = "config")
     @Data
     public class ConfigProperties {
         private String url;
         private String username;
     }
  3. config.yml 文件

    在resources 目录下新建 config 文件夹,在里面新建 config.yml 文件

     config:
       url: https://www.emanjusaka.top
       username: emanjusaka

测试验证

 package top.emanjusaka;
 ​
 import cn.hutool.extra.spring.SpringUtil;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import top.emanjusaka.properties.ConfigProperties;
 ​
 @SpringBootApplication
 public class Application {
     private static ConfigProperties configProperties;
 ​
     private static ConfigProperties getProperties() {
         if (configProperties == null) {
             configProperties = SpringUtil.getBean(ConfigProperties.class);
         }
         return configProperties;
     }
 ​
     public static void main(String[] args) {
         SpringApplication.run(Application.class, args);
         System.out.println("url:" + getProperties().getUrl());
     }
 ​
 }

成功读取 yml 文件:

image-20240705105932313

E9F80B5F-13B9-4BC3-A29D-1A6795E2B05C

在技术的星河中遨游,我们互为引路星辰,共同追逐成长的光芒。愿本文的洞见能触动您的思绪,若有所共鸣,请以点赞之手,轻抚赞同的弦。

原文地址: https://www.emanjusaka.top/2024/07/annotation-@PropertySource-yml

微信公众号:emanjusaka的编程栈