【问题标题】:CDI inject specific interface implementationCDI注入具体接口实现
【发布时间】:2021-03-02 17:40:19
【问题描述】:

假设我有一个接口Config 和两个实现这个接口的类:

class Config1: Config {
}

class Config2: Config {
}

我通过使用 Jackson 对 JSON 进行反序列化来创建其中一种实现,并希望在公共库中将其作为 CDI ApplicationScope bean 提供:

@Produces
@ApplicationScope
fun config: Config {
  return mapper.readValue(json, Config)
}

现在我有两个应用程序,App1 依赖于 Config1App2 依赖于 Config2。我想实现这样的行为,例如启动 App1 Config1 被注入或抛出异常,没有 bean 可以满足构造函数。不幸的是,这不起作用:

class App1 (val config: Config1) { }

有什么方法可以实现吗?或者我必须编写一个服务来进行实例检查?

【问题讨论】:

    标签: dependency-injection cdi


    【解决方案1】:

    您可能需要重新考虑这种方法。有了您所拥有的,您甚至无法执行instanceof 检查,因为您将获得一个代理,而不是实际的 bean 实例(因为您的生产者是 @ApplicationScoped)。

    在 CDI 中,bean 由它们的类型和它们的限定符定义。从您的描述中,我了解到您无论如何都需要区分这两个配置,因此将其抽象为界面是行不通的。您可以有两个生产者方法,每个方法用于一个配置并具有不同的限定符。每个方法看起来像这样:

    @Produces
    @ApplicationScoped
    @Config1Qualifier //some custom qualifier that you slap on it
    fun config: Config {
      return someFunctionThatResolvesIt()
    }
    

    它的注入点将如下所示(使用 Java 语法):

    @Inject
    @Config1Qualifier
    Config config;
    

    这种方法的好处是,只要你的生产者方法有正常的作用域(例如@ApplicationScoped),那么如果它们试图返回null,它就会自动被视为错误——看起来像无论如何你都在努力实现的目标。

    从完全不同的角度接近它,您可以采用当前的生产者方法并将@ApplicationScoped 更改为@Dependent@Singleton,它们都不使用代理并允许执行instanceof。但请注意,特别是 @Dependent 的行为可能与您想要的不同(假设您使用应用程序范围来保留单个实例)。

    【讨论】:

    • 这两个只是我的想法,您可能可以使用更多的调整,但描述相当笼统,我不得不对此做出疯狂的假设。例如,不清楚你是否总是只实例化其中一个配置(这就是生产者似乎在做的 ATM),这意味着你的一个应用程序总是抛出错误?
    猜你喜欢
    • 2016-07-25
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    • 2019-04-09
    相关资源
    最近更新 更多