我有一些 bean(多种类型,CDI、@Stateless
和 @Singleton
bean)。他们的一些字段应该从数据库值中注入(inject)。
public class MyBean {
@Inject
@DbConfigValue(MyConfig.HOST)
String host;
}
所以我添加了一个自定义
@Qualifier
( DbConfigValue
) 由生产者使用。生产者从数据库中读取并缓存配置值并将它们注入(inject)到 bean 中。@Singleton
@Lock(LockType.READ)
public class Configuration {
@Produces
@Dependent
@DbConfigValue
public String getDbConfigValue(InjectionPoint point) {
// get key for the config-value from qualifier-annotation of the injected field
String key = point.getAnnotated().getAnnotation(DbConfigValue.class).value();
// i have read+cached database config values in @PostConstruct before
return cachedConfigValues.get(key);
}
}
这适用于初始注入(inject)/bean 构造。一些网络教程建议使用这种方法。
现在,我认为假设配置值(如果存储在 DB 中)可能会在运行时发生变化是合理的。因此,每当管理员更改数据库配置值时,我目前都会触发 CDI 事件。
问题 : 有没有办法将值重新注入(inject)到已经初始化的 bean 实例的字段中?或者注入(inject)总是只与实例创建有关?
例如。我有……与此类似:
public class MyEventListener {
@Inject
BeanManager beanManager;
@Asynchronous
public void onDbConfigValueChangedEvent (@Observes(during = TransactionPhase.AFTER_SUCCESS) DbConfigValueChangedEvent event) {
try {
// could be filtered by custom qualifier:
Set<Bean<?>> beans = beanManager.getBeans(Object.class,new AnnotationLiteral<Any>() {});
for (Bean<?> bean : beans) {
Set<InjectionPoint> points = bean.getInjectionPoints();
// What now? javax.enterprise.inject.spi.Bean is the
// bean-representation only.
// Can I somehow resolve the actual bean-instances here?
// Then update Field via Reflection?
}
}
catch(Exception e){
// ...
}
}
}
我也考虑过DeltaSpike其中有一些注入(inject)控制方法。但是,我确实只找到了注入(inject)新 bean 实例的方法,甚至是使用新的或空的CreationalContexts (之后的 bean 不是 CDI 管理的)
请注意:我知道我可以通过注入(inject)配置并显式获取每个请求的当前值来解决这个特定的用例,如下所示:
public class MyBean {
@Inject
Configuration config;
public void someMethod(){
String host = config.getConfig(MyConfig.HOST);
// ...
}
}
但是,我想知道一般的问题:是否支持重新注入(inject)?或者如果没有,规范(CDI 或 Java EE)是否禁止它?
最佳答案
根据您的数据库的快/慢,这可能会很昂贵。您可能会在生产者方法中利用一些缓存机制。
利用 Instance
注入(inject)机制,延迟加载实际注入(inject)的 bean。
你的生产者(可能利用一些缓存来避免数据库调用所有的书)
@Singleton
@Lock(LockType.READ)
public class Configuration {
@Produces
@RequestScoped //May fail if not in a request-context, but for ejb-calls, it is guaranteed to work as CDI has EJB Request Context
@DbConfigValue
public String getDbConfigValue(InjectionPoint point) {
// get key for the config-value from qualifier-annotation of the injected field
String key = point.getAnnotated().getAnnotation(DbConfigValue.class).value();
// i have read+cached database config values in @PostConstruct before
return cachedConfigValues.get(key);
}
}
以及注入(inject)点:
@SessionScoped
public class MyBean {
@Inject
@DbConfigValue(MyConfig.HOST)
private Instance<String> host;
public void doSomething() {
String myHost = host.get(); // of course will throw exception if value is failing. It will be resolved with every request.
}
}
关于java - 有没有办法重新注入(inject)/更新注入(inject)的 bean 字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37993435/