【问题标题】:Spring Boot: how to configure a set of implementations to inject?Spring Boot:如何配置一组实现注入?
【发布时间】:2026-01-13 03:50:02
【问题描述】:

在我的 Spring Boot 应用中,我有事件,应该根据环境以各种方式报告

我定义了interface IReporter 和几个实现,即LogReporterEmailReporterRpcReporter。未来也可能会出现新的实现。

现在我希望使用部分记者报告我的事件。子集必须在应用配置中指定如下(例如):

events.reporters=LogReporter,EmailReporter

events.reporters=${EVENT_REPORTERS}

或类似的东西。

因此,我希望处理事件的组件(比如class EventHandler)能够神奇地注入仅包含必要实现的List<IReporter> myReporters。 当然,如果创建了新的实现,唯一需要更新的必须是应用配置(而不是EventHandler 的代码)。

我熟悉注入所有可用的实现,只有@Primary 实现,或者用@Qualifier 挑选的特定实现。但看起来这些并不能解决我的问题。

【问题讨论】:

    标签: spring spring-boot dependency-injection configuration


    【解决方案1】:
    class EventHandler {
    
            @Value("${events.reporter}")
            List<String> requiredImplementation;
    
            @Autowired
            List<IReporter> myReporters;
    
            public List<IReporter> getRequiredImplementation() {
                return myReporters.stream()
                        .filter(reporter -> requiredImplementation.contains(reporter.getClass().getSimpleName()))
                        .collect(Collectors.toList());
            }
        }
    

    编辑: 如果我们希望框架仅自动装配所需的 bean,我可以考虑一种选择,我们可以探索 @ConditionalOnExpression。

    例如:

    @Component
    @ConditionalOnExpression("#{'${events.reporter}'.contains('LogReporter')}")
    Class LogReporter {
    }
    
    @Component
    @ConditionalOnExpression("#{'${events.reporter}'.contains('EmailReporter')}")
    Class EmailReporter {
    }
    

    【讨论】:

    • 嗯,魔法在这里手动完成。注入所有东西并过滤掉不需要的东西。但是,该框架将尝试实例化所有报告器。其中一些可能由于缺少资源而失败。比如我不使用EmailReporter,就不会提供访问SMTP的参数。
    • 编辑了我的答案以包含一个选项,用于根据属性值仅自动配置所需的 bean。
    • 谢谢,@kumar-v 这正是我想要的 - 条件bean
    • @NikS 很高兴知道它有帮助。如果这解决了你的问题,你能接受这个答案吗?
    最近更新 更多