CDI注入特定接口实现

时间:2021-03-02 17:40:19

标签: dependency-injection cdi

假设我有一个接口 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) { }

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

1 个答案:

答案 0 :(得分: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,它们都不使用代理,并且允许执行 {{1 }}。但请注意,特别是 instanceof 的行为可能与您想要的有所不同(假设您使用应用范围来保持单一实例)。