Spring Boot 2.6.6中定制bootstrapRegistryInitializers的配置与时机问题
针对你的Spring Boot 2.6.6场景的解答
问题1:能否在app.run(args)执行前获取Spring属性值?
可以,但无法直接拿到完整的Spring环境属性,需要手动提前加载指定属性源:
- 默认情况下,Spring的
ConfigurableEnvironment是在run()方法启动流程中逐步构建的,会整合命令行、配置文件、环境变量等所有属性源。 - 如果要在
run()前获取属性,你可以手动初始化环境并加载目标属性源,示例代码如下:
SpringApplication app = new SpringApplication(YourApp.class); // 初始化标准环境实例 ConfigurableEnvironment env = new StandardEnvironment(); // 加载本地配置文件,可按需添加命令行参数、系统变量等其他属性源 env.getPropertySources().addFirst(new ResourcePropertySource("classpath:application.yml")); app.setEnvironment(env); // 此时可获取vault.ttl属性 String vaultTtl = env.getProperty("vault.ttl");
- 注意:这种方式只能获取你手动加载的属性源中的值,外部配置中心(如Nacos、Consul)的动态属性因为还没触发拉取,是拿不到的。
问题2:能否在应用启动后配置SpringApplication的bootstrapRegistryInitializers并生效?
完全不行。
bootstrapRegistryInitializers是Spring Boot启动流程中最早期的扩展点,作用于bootstrap上下文(若启用Spring Cloud Bootstrap)或应用上下文初始化的前置阶段,仅在run()方法执行过程中生效一次。- 一旦应用启动完成,Spring上下文已初始化完毕,所有Bean都已创建,此时修改
bootstrapRegistryInitializers不会对现有上下文产生任何影响,也无法触发重新初始化。如果要让新的bootstrapRegistryInitializers生效,只能重新启动应用。
适配你的Vault配置场景的建议
你不需要绕到bootstrapRegistryInitializers里拿属性配置HttpComponentsClientHttpRequestFactory,直接在AbstractVaultConfiguration的子类中注入Environment即可获取vault.ttl:
@Configuration public class CustomVaultConfiguration extends AbstractVaultConfiguration { @Autowired private Environment env; @Override public ClientHttpRequestFactory clientHttpRequestFactory() { String ttl = env.getProperty("vault.ttl"); // 根据ttl配置HttpClientBuilder HttpClientBuilder httpClientBuilder = HttpClientBuilder.create() .setConnectionTimeToLive(Long.parseLong(ttl), TimeUnit.SECONDS); // 按需添加其他HttpClient配置 return new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build()); } // 实现其他必要方法,比如指定Vault端点、认证方式 @Override public VaultEndpoint vaultEndpoint() { return VaultEndpoint.create("your-vault-host", 8200); } @Override public ClientAuthentication clientAuthentication() { // 配置你的认证方式,比如TokenAuthentication return new TokenAuthentication("your-vault-token"); } }
如果你的场景必须用到bootstrapRegistryInitializers,可以在run()前先手动加载属性,再初始化对应的BootstrapRegistryInitializer并添加到SpringApplication中:
public static void main(String[] args) { SpringApplication app = new SpringApplication(YourApp.class); // 先加载属性 ConfigurableEnvironment env = new StandardEnvironment(); env.getPropertySources().addFirst(new ResourcePropertySource("classpath:application.yml")); app.setEnvironment(env); String vaultTtl = env.getProperty("vault.ttl"); // 创建自定义的BootstrapRegistryInitializer BootstrapRegistryInitializer customInitializer = registry -> { registry.register(ClientHttpRequestFactory.class, context -> { HttpClientBuilder builder = HttpClientBuilder.create() .setConnectionTimeToLive(Long.parseLong(vaultTtl), TimeUnit.SECONDS); return new HttpComponentsClientHttpRequestFactory(builder.build()); }); }; // 添加到SpringApplication app.addBootstrapRegistryInitializer(customInitializer); app.run(args); }
内容的提问来源于stack exchange,提问作者julus
相关产品推荐
相关产品推荐

