假设我有一个接口 Config
和两个实现这个接口的类:
class Config1: Config {
}
class Config2: Config {
}
我通过使用 Jackson 反序列化 JSON 来创建其中一个实现,并希望将其作为 CDI ApplicationScope bean 提供到公共库中:
@Produces
@ApplicationScope
fun config: Config {
return mapper.readValue(json, Config)
}
现在我有两个应用程序,App1
依赖于 Config1
,App2
依赖于 Config2
。我想实现的行为,例如启动 App1 Config1 被注入或抛出异常,没有 bean 来满足构造函数。不幸的是,这不起作用:
class App1 (val config: Config1) { }
有什么办法可以实现吗?或者我必须编写一个服务来进行实例检查?
答案 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
的行为可能与您想要的有所不同(假设您使用应用范围来保持单一实例)。