使用@PropertySource注解加载自定义yml文件时无法获取数据

本文介绍了如何在Spring中实现YamlPropertySourceFactory,以支持从YAML文件读取配置。首先创建了一个工具类,继承PropertySourceFactory并实现了createPropertySource方法,用于加载YAML文件。接着,通过在@PropertySource注解中指定factory参数,使用自定义的YamlPropertySourceFactory来解析配置。这种方法扩展了Spring默认的.properties文件解析能力。

因为spring中PropertySource的默认实现是properties类型文件的解析。

可以实现一个解析yaml文件的工具类,实现PropertySourceFactory接口。

第一步:实现工具类

public class YamlPropertySourceFactory implements PropertySourceFactory {

    /**
     * PropertySourceFactory针对yml的实现类
     * @param name
     * @param resource
     * @return
     * @throws IOException
     */
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
        return sources.get(0);
    }
}

第二步,配置使用YamlPropertySourceFactory。

@Component
// 在PropertySource后添加factory指定使用自定义实现的YamlPropertySourceFactory解析yml
@PropertySource(value = {"classpath:youryaml.yml"}, factory = YamlPropertySourceFactory.class)
@ConfigurationProperties("yourproprety")

 

 
<think>嗯,用户的问题是关于如何在Spring Boot自定义PropertySource来读取yml配置文件,并且动态修改部分配置,同使用@PropertySource注解。我需要先理清楚Spring Boot处理配置文件的机制,以及如何扩展它。 首先,我记得Spring Boot默认支持application.yml加载,这是通过ConfigFileApplicationListener处理的,它会自动加载特定位置的配置文件。但用户想要自定义PropertySource,可能需要绕过默认的机制,或者扩展它。 用户提到使用@PropertySource注解,可能是因为这个注解默认支持yml,需要配合自定义PropertySourceFactory,比如示例中的那个类。但用户希望用这个注解,所以可能需要另一种方式将自定义PropertySource添加到环境中。 接下来,我需要思考如何手动加载yml文件YamlPropertySourceLoader是Spring Boot提供的用于加载yml的工具类,可以返回一个PropertySource列表。所以用户需要自己编写代码来加载yml文件,获取其中的属性,然后创建自定义PropertySource。 动态修改配置的话,可能需要使用可写的属性源,或者覆盖已有的属性。例如,使用MapPropertySource,它基于一个Map,可以修改其中的值。或者自定义一个PropertySource,允许动态更新。 步骤可能包括: 1. 实现EnvironmentPostProcessor接口,在应用启动早期阶段添加自定义PropertySource。 2. 使用YamlPropertySourceLoader加载yml文件内容,生成PropertySource。 3. 将这些PropertySource添加到ConfigurableEnvironment中。 4. 如果需要在运行动态修改,可能需要结合Spring Cloud的RefreshScope或者其他机制,或者维护一个可修改的PropertySource。 但是用户没有提到Spring Cloud,可能需要纯Spring Boot的解决方案。动态修改的话,可能需要在运行获取ConfigurableEnvironment,然后获取或创建对应的PropertySource进行修改。 另外,还需要考虑配置的优先级,确保自定义PropertySource在合适的位置,能够覆盖默认配置或者被其他配置覆盖。 可能遇到的问题包括:yml文件的路径如何指定,如何确保在正确的间点加载配置,以及动态修改后的配置如何被应用(比如需要重启或刷新Bean)。 参考用户提供的引用内容,他们已经有了一个自定义PropertySourceFactory,但用户现在想用@PropertySource注解,所以需要另一种方式注册PropertySource。 总结可能的实现步骤: - 自定义一个EnvironmentPostProcessor,在postProcessEnvironment方法中加载yml文件,创建PropertySource并添加到环境中。 - 使用YamlPropertySourceLoader来解析yml文件。 - 如果需要动态修改,可能需要将PropertySource设计为可变的,比如使用MutablePropertySources或者自定义的实现,允许后续更新。 然后,动态修改可以通过获取环境中的PropertySource,进行值的替换。例如,从环境中获取MutablePropertySources,找到对应的PropertySource,然后修改其内部的属性。 需要注意的是,动态修改配置后,已经存在的Bean可能会自动更新,除非使用@RefreshScope或其他机制。这部分可能需要用户自己处理。 因此,回答应该分为两部分:一是如何自定义加载yml配置,二是在运行动态修改配置的方法,并指出可能的限制和需要处理的问题。</think>### 分步实现自定义PropertySource读取YML并动态修改配置 #### 1. **自定义EnvironmentPostProcessor** Spring Boot允许通过`EnvironmentPostProcessor`接口在应用启动早期阶段干预配置加载过程,无需依赖`@PropertySource`注解。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertySource; import org.springframework.core.io.ClassPathResource; import java.io.IOException; import java.util.List; public class CustomYamlPropertySource implements EnvironmentPostProcessor { private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { try { // 加载指定路径的YML文件(示例为classpath:custom-config.yml) ClassPathResource resource = new ClassPathResource("custom-config.yml"); List<PropertySource<?>> sources = loader.load("dynamicYamlSource", resource); // 将自定义配置添加到环境末尾(优先级最低)或开头(优先级最高) sources.forEach(envSource -> environment.getPropertySources().addLast(envSource)); } catch (IOException e) { throw new RuntimeException("加载YML配置文件失败", e); } } } ``` #### 2. **注册EnvironmentPostProcessor** 在`src/main/resources/META-INF/spring.factories`文件中声明自定义处理器: ```properties org.springframework.boot.env.EnvironmentPostProcessor=com.example.CustomYamlPropertySource ``` #### 3. **动态修改配置** 通过操作`ConfigurableEnvironment`实现运行配置修改: ```java import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import java.util.HashMap; import java.util.Map; public class ConfigUpdater { private final ConfigurableEnvironment environment; public ConfigUpdater(ConfigurableEnvironment environment) { this.environment = environment; } public void updateProperty(String key, Object value) { // 获取或创建可修改的PropertySource Map<String, Object> configMap = new HashMap<>(); configMap.put(key, value); MapPropertySource dynamicSource = new MapPropertySource("dynamicOverride", configMap); // 覆盖原有配置(高优先级) environment.getPropertySources().addFirst(dynamicSource); } } ``` #### 实现原理说明 1. **配置加载阶段**:通过`EnvironmentPostProcessor`在Spring Boot启动加载外部YML文件,生成`PropertySource`并注入到环境中[^1]。 2. **优先级控制**:通过`addFirst()`或`addLast()`方法决定配置的覆盖顺序。 3. **动态修改**:通过添加高优先级的`MapPropertySource`实现运行覆盖配置值,但需注意已初始化的Bean可能需要手动刷新。 #### 注意事项 - **配置覆盖规则**:后添加的`PropertySource`优先级更高,`addFirst()`会覆盖后续源的配置。 - **Bean刷新机制**:动态修改后,需通过`@RefreshScope`(需配合Spring Cloud)或重启应用使配置生效。 - **线程安全性**:动态修改操作需确保线程安全,避免并发问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值