【问题标题】:Conditionally choose bean based on other beans根据其他bean有条件地选择bean
【发布时间】:2019-03-08 07:52:27
【问题描述】:

说我有:

interface A { ... }
class A1 implements A { ... }
class A2 implements A { ... }

@Lazy
@Configuration
class SpringConfig {
  @Bean
  A a1(DepA11 depA11, DepA12 depA12, ...) {
  }

  @Bean
  A a2(DepA21 depA21, DepA22 depA22, ...) {
  }
}

现在假设有一些复杂的逻辑依赖于一些返回 int 的注入依赖项:

int choose(DepChoose1 depChoose1, DepChoose2 depChoose2, ...) {
  // Complex logic that depends on depChoose1, depChoose2, ...
  int res = ...; 
  return res;
}

我希望 Spring 根据返回值自动装配 a1a2

必须不要实例化另一个 bean(或一般的 bean - 我们可以有 a3a4、...),因为它们中的每一个都会在启动时产生繁重的处理,并且还会产生副作用如果最初要选择另一个 bean,则必须避免这种情况。

A1A2 是供系统其他部分使用的类似流的项目源。它们的一些(非直接)依赖项通过@PostConstruct 进行了初始化。

它们的依赖也是基于推送的。无论他们获取什么,他们都会推送到B,然后转发给其他消费者。因此,仅初始化它们会产生不必要的推送。

我想过使用@Conditional,但它是inherently doesn't support dependencies

在 Spring 中是否有一种简洁的方法可以做到这一点?

【问题讨论】:

    标签: java spring


    【解决方案1】:

    也许不是您正在寻找的解决方案,但如果实例化(未使用的)bean 成本太高,请改为实例化工厂。

    【讨论】:

    • 我如何绕过实例化依赖项?例如。 A1Factory 需要 DepA11, DepA12, ... 才能创建 A1。然后,我还需要为这些以及它们的依赖项创建工厂,然后......为什么我需要 Spring :)
    • 恐怕我们在这里处理的是XY problem。这个问题不是很具体,你想达到什么目标,以及有什么限制。一般来说,你会遇到的是 Spring 在某个时间点执行初始配置处理和实例化,如果你的实例化逻辑依赖于其他 bean,那对你来说还为时过早。 Lazy-init bean 似乎与您的问题不匹配。
    • 我过去通过创建两个 Spring 上下文处理过类似的问题,第二个基于第一个中的一些计算进行参数化(通过带有属性占位符的 XML 配置 - 它们可以使用即使对于 bean refs / bean 类名!),但很难说这在你的情况下是否会过分杀伤力,或者它是否可以使用。
    • 谢谢 Jiri - 我编辑了答案以添加更多位,但我不确定如何更具体并且不失去我所追求的解决方案的一般性。
    【解决方案2】:

    两种可能:

    • 如果choose 总是返回相同的值,换句话说,你总是希望在你的上下文中拥有a1a2,那么只需定义一个@Bean 方法,在其中执行检查并返回a1a2 来自它
    • 如果choose返回不同的值,那么创建一个新的bean来充当工厂,所以不是注入a1a2你将注入工厂然后调用例如getBean() ,然后调用 choose 并返回 a1a2

    【讨论】:

    • "choose 总是返回相同的值" 是的,这正是我想要的,但如果我这样做,那么所有依赖项都将被实例化,这就是成本所在。我该如何解决?
    • @levantpied @Bean 方法只会实例化所需的依赖项
    • 从 OP 的描述看来,choose() 的结果取决于已经初始化的其他一些 bean - 在实例化 a1a2 之前执行检查可能会很紧张,但 depChoose1depChoose2 已经处于一致状态。
    • @JiriTousek 没错。我希望depChoose1depChoose2 被完全实例化,所以我可以使用他们的方法来确定是实例化A1 还是A2,但我想避免实例化A2 和其中任何一个DepA2x如果我选择A1,则依赖项。
    猜你喜欢
    • 2020-12-24
    • 1970-01-01
    • 2015-08-15
    • 2011-12-16
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多