@PropertySource注解

@PropertySource 注解是 Spring 3.1 开始引入的配置类注解。通过 @PropertySource 注解将 properties 配置文件中的值存储到 Spring 的 Environment中,Environment 接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。也可以使用@Value注解用${}占位符注入属性。

但是,默认情况下,@PropertySource 不会加载 yaml 文件,具体可查看官方文档 boot-features-external-config-yaml-shortcomings

自定义 PropertySourceFactory

从 Spring 4.3 开始,@PropertySource 带有工厂属性。我们可以利用它来提供我们对 PropertySourceFactory 的自定义实现,该实现将处理YAML 文件处理。

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) 
      throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
}

如我们所见,实现单个 createPropertysource 方法已经足够了。

在我们自定义的实现中,我们首先用 YamlPropertiesFactoryBean 将 yaml 格式的资源转换成 java.util.Properties 对象。然后我们只返回一个 PropertiesPropertySource 的新实例,该实例是一个包装器,允许 Spring 读取解析的属性。

@PropertySource 和 YAML 实战

创建一个自定义 yaml 文件 custom.yml

server:
  machine:
    ip: 127.0.0.1
    port: 20086

  switches:
    - on
    - off

创建一个配置类 CustomConfig

@Configuration
@Data
@PropertySource(value = "classpath:custom.yml", factory = YamlPropertySourceFactory.class)
@ConfigurationProperties(prefix = "server")
public class CustomConfig {
    private Map<String,String> machine;
    private List<String> switches;
}

class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public org.springframework.core.env.PropertySource<?> createPropertySource(String name, EncodedResource encodedResource)
            throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
}

这里为了方便,直接将 YamlPropertySourceFactory 类和 CustomConfig 类写在一起了。

测试

@SpringBootTest
public class CustomConfigTest {
    @Autowired
    private CustomConfig customConfig;

    @Test
    public void configTest() {
        System.out.println(customConfig.toString());
    }
}

结果:

CustomConfig(machine={ip=127.0.0.1, port=20086}, switches=[true, false])

本文参考:
@PropertySource with YAML Files in Spring Boot
Inject a Map from a YAML File with Spring

标签: none

评论已关闭