如何在Spring Actuator端点中自动注入FactoryBean本身实例
Spring注入FactoryBean本身的标准实践与顺序问题解决方案
注入FactoryBean本身的基础规则
Spring容器针对FactoryBean的获取有内置约定:
- 按名称注入时,给bean名添加
&前缀即可拿到FactoryBean实例本身,不加前缀会返回FactoryBean#getObject()生成的业务对象。 - 按类型注入时,只要注入点的类型声明为FactoryBean的实现类本身(而非其生成的对象类型),Spring默认就会返回FactoryBean实例,无需额外配置前缀。
实例化顺序问题的最优解决方案
你遇到的注入Map为空的问题,本质是Actuator端点的初始化优先级高于StreamsBuilderFactoryBean,以下方案按推荐度排序:
方案1:ObjectProvider延迟注入(最优)
直接通过Spring提供的ObjectProvider实现依赖的延迟获取,完全规避实例化顺序依赖,无需硬编码bean名、无需额外监听事件、无需自定义上下文工具类:
// 你的Actuator端点类示例 @RestControllerEndpoint(id = "streams") public class StreamsOperateEndpoint { private final ObjectProvider<Map<String, StreamsBuilderFactoryBean>> factoriesProvider; // 构造器注入即可,Spring会自动注入对应ObjectProvider public StreamsOperateEndpoint(ObjectProvider<Map<String, StreamsBuilderFactoryBean>> factoriesProvider) { this.factoriesProvider = factoriesProvider; } // 在实际使用FactoryBean的方法中再获取实例 @PostMapping("/start-all") public void startAllStreams() { Map<String, StreamsBuilderFactoryBean> topologyFactories = factoriesProvider.getIfAvailable(Collections::emptyMap); topologyFactories.values().forEach(StreamsBuilderFactoryBean::start); } }
方案2:SmartInitializingSingleton预加载
如果需要在应用启动阶段就缓存所有FactoryBean实例,可以让Actuator端点类实现SmartInitializingSingleton接口,其afterSingletonsInstantiated方法会在所有非懒加载单例Bean全部初始化完成后触发,比ApplicationReadyEvent更轻量,也不需要依赖自定义上下文工具:
@RestControllerEndpoint(id = "streams") public class StreamsOperateEndpoint implements SmartInitializingSingleton { private Map<String, StreamsBuilderFactoryBean> topologyFactories; private final ListableBeanFactory beanFactory; public StreamsOperateEndpoint(ListableBeanFactory beanFactory) { this.beanFactory = beanFactory; } @Override public void afterSingletonsInstantiated() { this.topologyFactories = beanFactory.getBeansOfType(StreamsBuilderFactoryBean.class); } }
你当前使用的ApplicationReadyEvent监听方案本身可运行,只是耦合了自定义的ApplicationContext工具类,用Spring自带的扩展点实现会更符合规范。
内容的提问来源于stack exchange,提问作者maow
相关产品推荐
相关产品推荐

