【发布时间】:2018-01-10 13:58:02
【问题描述】:
我有 两个 bean 实现了一个接口:
@Storage(StorageType.LOCAL)
public class LocalStorage implements StorageService {
// [...]
}
和
@Storage(StorageType.REMOTE)
public class RemoteStorage implements StorageService {
// [...]
}
在服务类中,我使用的是注入的 StorageService:
@Stateless
public class DocumentService {
@Inject
@Storage(StorageType.REMOTE)
private StorageService storageService;
// [...]
}
这很好用,但是我希望能够从外部配置 StorageType,而无需更改源代码。
所以我创建了一个Producer:
@Singleton
public class StorageServiceProducer {
@Inject
@ConfigurationValue("storage.type") // Injects values from a properties file
private String storageType;
@Produces
public StorageService produceStorageService(InjectionPoint injectionPoint) {
if (storageType.equals("remote")) {
return new RemoteStorage();
} else {
return new LocalStorage();
}
}
}
...并从我的 bean 中删除了 @Storage 注释:
public class LocalStorage implements StorageService {
// [...]
}
和
public class RemoteStorage implements StorageService {
// [...]
}
但是现在我得到一个模糊依赖异常,大概是因为生产者本身的存在。为了强制使用生产者,我发现可以使用“@Vetoed”注解。
这似乎可行,但由于不再管理 bean,我的实现中的任何注入值都丢失了:
public class RemoteStorage implements StorageService {
@Inject
@ConfigurationValue("project.id")
private String projectId;
// [...]
}
所以这是我的问题:
- 这是拥有一个可配置的“动态”生产者的正确方法吗?
- 我使用@Alternatives 成功了,但这与Annotation 方法有相同的缺点:如果我想更改实现,我需要更改beans.xml 文件
- 我怎样才能做到这一点?
编辑:我正在使用 CDI 1.2 和 bean-discovery-mode="all"
【问题讨论】:
标签: jakarta-ee cdi