springboot-SPI-修改配置文件
1. 编写代码
package com.config; import java.util.HashMap; import java.util.Map; import java.util.Objects; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.context.event.ApplicationPreparedEvent; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.boot.env.OriginTrackedMapPropertySource; import org.springframework.boot.logging.DeferredLog; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; public class BootStrapConfigProcessor implements EnvironmentPostProcessor, ApplicationListener<ApplicationEvent>, Ordered { private static final DeferredLog LOGGER = new DeferredLog(); @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { if (application.getWebApplicationType() == WebApplicationType.SERVLET) { replaceConfig(environment, application); } } @Override public int getOrder() { return 0; } @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationPreparedEvent) { LOGGER.replayTo(BootStrapConfigProcessor.class); } } private void replaceConfig(ConfigurableEnvironment environment, SpringApplication application) { LOGGER.info("开始替换配置值==============="); MutablePropertySources sources = environment.getPropertySources(); Map<String, Object> newConfigMap = new HashMap<>(); for (PropertySource<?> ps : sources) { if (!(ps instanceof OriginTrackedMapPropertySource)) { continue; } OriginTrackedMapPropertySource ops = (OriginTrackedMapPropertySource) ps; String[] names = ops.getPropertyNames(); for (String name : names) { Object value = ops.getProperty(name); if (value instanceof String) { LOGGER.info("原始配置:" + name + ":" + value); } // 替换新值 if (Objects.equals("test.config.name", name)) { newConfigMap.put(name, "newTestValue"); LOGGER.info("替换新的值:" + name + ": newTestValue"); } } } newConfigMap.put("test.config.password", "password123"); LOGGER.info("添加新值:test.config.password: password123"); // 将新值注入配置中 if (!newConfigMap.isEmpty()) { environment.getPropertySources() .addFirst(new MapPropertySource("BootStrapConfigProcessor.properties", newConfigMap)); } LOGGER.info("换值完毕==============="); } }
2.配置
resources/META-INF/spring.factories
# Environment Post Processor org.springframework.boot.env.EnvironmentPostProcessor=\ com.config.BootStrapConfigProcessor org.springframework.context.ApplicationListener=\ com.config.BootStrapConfigProcessor
3.业务使用
@Value("${test.config.name}") private String testConfigName; @Value("${test.config.password}") private String testConfigPassword;
4. 备注
测试版本 2.3.4.RELEASE
5. 其他
由于这个类执行时日志系统还没有初始化所有使用了DeferredLog来打印日志,可是怎么都不输出日志
最后定位发现先是springboot热启动[restartedMain] RestartLauncher.java类加载器导致,将pom中的spring-boot-devtools依赖去掉问题解决