页面加载中...

解决Spring的PropertySource注解不能加载yml配置文件的问题

| Spring Boot | 0 条评论 | 1050浏览

踩过的一个坑

记得之前曾经总结过一篇文章:Springboot中yml文件读取。 在一个modul下新建配置yml配置文件,esb-pool-config.yml:

# esb服务同步池配置
sapConfig:
    DBCHNESBCFG:
        type: sc
        name: 自由电渠
        hibernate: hibernate.cfg.busa.xml
        esb: 10.113.161.11:51000
    DBCHNESBBJ:
        type: sc
        name: 北京环境
        hibernate: todo.xml
        esb: 172.18.231.104:51000
    DBCHNESBBJ1:
        type: fb
        name: 北京发布环境2
        hibernate: todo1.xml
        esb: 172.18.231.104:51000

而后按部就班在bean里面引用里面的配置:

@Component
@PropertySource("classpath:esb-pool-config.yml")
@ConfigurationProperties
public class EsbPoolConfig {
    /**
     * 配置文件里面的配置,默认会全部加载到里面来的
     */
    private Map<String,Entry> sapConfig = new HashMap<>();

    // getter settter方法
}

结果发现根本就读取不到配置,sapConfig一直empty。 有点懵。 然后把上述配置写在程序启动的application.yml配置文件里面的,bean却能读到这些配置。 然后更懵了。

开始有点怀疑是否是@PropertySource注解的问题,根本就没有读到我自定义的yml配置文件。

看了下@PropertySource注解的文档,发现其只支持*.properties格式的配置文件。 有点无语。 然后尝试将上述yml配置文件该为properties配置文件:

sap.sapConfig.DBCHNESBCFG.type=sc
sap.sapConfig.DBCHNESBCFG.name=自由电渠
sap.sapConfig.DBCHNESBCFG.hibernate=hibernate.cfg.busa.xml
sap.sapConfig.DBCHNESBCFG.esb=10.113.161.11:51000
sap.sapConfig.DBCHNESBBJ.type=sc
sap.sapConfig.DBCHNESBBJ.name=北京环境
sap.sapConfig.DBCHNESBBJ.hibernate=todo.xml
sap.sapConfig.DBCHNESBBJ.esb=172.18.231.104:51000
sap.sapConfig.DBCHNESBBJ1.type=fb
sap.sapConfig.DBCHNESBBJ1.name=北京发布环境1
sap.sapConfig.DBCHNESBBJ1.hibernate=todo1.xml
sap.sapConfig.DBCHNESBBJ1.esb=172.18.231.104:51000

启动工程,bean读取到了properties配置文件里面的配置了。

解决

貌似问题已经解决了,其实并不然。由于properties的格式远不如yml配置的清晰,我还是尝试下能否继续使用PropertySource来加载yml配置文件。

PropertySource注解中有一个参数:factory,可以指定PropertySourceFactory,通过PropertySourceFactory可以指定加载配置文件的方式。

于是一个实现了简单的可以加载yml的PropertySourceFactory:

public class YmlConfigFactory extends DefaultPropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        String sourceName = name != null ? name : resource.getResource().getFilename();
        if (!resource.getResource().exists()) {
            //不存在就返回一个空的把
            return new PropertiesPropertySource(sourceName, new Properties());
        }
        if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
            //yml这里手动加进去
            YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
            factory.setResources(resource.getResource());
            factory.afterPropertiesSet();
            Properties propertiesFromYaml = factory.getObject();
            return new PropertiesPropertySource(sourceName, propertiesFromYaml);
        }
        return super.createPropertySource(name, resource);
    }
}

而后,在上述bean里面引入该factory:

@Component
@PropertySource(value = "classpath:esb-pool-config.yml",factory = YmlConfigFactory.class)
@ConfigurationProperties
public class EsbPoolConfig {
    /**
     * 配置文件里面的配置,默认会全部加载到里面来的
     */
    private Map<String,Entry> sapConfig = new HashMap<>();

    // getter settter方法
}

于是,问题得到解决。PropertySource也能加载yml配置文件了。

总结

默认的PropertySource是不支持加载yml/yaml等配置文件的,它默认只会加载properties配置文件。通过实现PropertySourceFactory接口,然后在注解的factory属性指定,可以自定义加载配置文件的方式。当然,也不仅仅只是yml,其他的配置方式,只要最后能够支持封装成Properties对象,都可以应用到。

发表评论

最新评论

    来第一个评论吧!