У меня есть некоторые бобы (нескольких типов, CDI, @Stateless
и @Singleton
бобы). Некоторые из полей должны вводиться из значений базы данных.Есть ли способ для повторного ввода/обновления инжектируемых полей бобов?
public class MyBean {
@Inject
@DbConfigValue(MyConfig.HOST)
String host;
}
Так что я добавил пользовательские @Qualifier
(DbConfigValue
), используемый Producer. Производитель считывает и кэширует значения конфигурации из базы данных и вводит их в 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);
}
}
Это хорошо работает для первоначальной инжекционной/бобовой конструкции. Некоторые веб-учебные пособия предлагают такой подход.
Теперь, я думаю, разумно предположить, что значения конфигурации, если они хранятся в БД, могут меняться во время выполнения. Таким образом, всякий раз, когда администратор изменяет значение конфигурации базы данных, я в настоящее время запускаю CDI-событие.
Вопрос: есть ли способ повторно вставить значения в поля уже инициализированных экземпляров bean-экземпляров? Или инъекция всегда связана только с созданием экземпляра?
E.g. У меня было с. похожее на это в виду:
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, который имеет некоторые методы для литья под контролем. Тем не менее, я только нашел методы для ввода в новые экземпляры bean или даже с новыми или null-CreationalContexts (beans not CDI-managed after)
Обратите внимание: я знаю, что могу решить этот конкретный прецедент путем введения конфигурации и явно получать текущие значения для каждого запроса, как это:
public class MyBean {
@Inject
Configuration config;
public void someMethod(){
String host = config.getConfig(MyConfig.HOST);
// ...
}
}
Однако, я задаюсь вопросом о вопросе в целом: существует ли какая-либо поддержка повторной инъекции? Или, если нет, запрещают ли спецификации (CDI или Java EE)?
Thx, полезно, но не совсем то, что я хотел: это запрос на инъекцию (через 'Instance.get()') по каждому запросу (каждый вызов 'doSomething'). Поэтому он похож на мой последний фрагмент ('config.getConfig()'), хотя вам снова удалось применить метод Producer. Но я скорее хотел повторно вводить инъекцию только тогда, когда было запущено событие CDI. И спросил себя, можно ли повторно ввести из ** вне ** ('MyEventListener') ** в ** все запущенные экземпляры bean-экземпляров. – Ben
В идеале производитель может сохранить значение в кеше, которое может быть обновлено в любое время (при его изменении только продюсер может прослушивать событие cdi и обновлять кеш), и обновление будет подхвачено всеми экземпляров. Reinjecting, imo просто не выглядит правильным в этом контексте – maress
Да, значения кэшируются и обновляются только после изменения. Фактически, я даже уже изменил свой код на решение, подобное этому для этой конкретной проблемы. Однако, как упоминалось в этом вопросе, я сам спросил себя, есть ли поддержка для повторной инъекции в JavaEE/CDI. Просто из любопытства и для возможного использования в будущем. Итак, если вы говорите «не так в этом контексте», знаете ли вы о решениях для повторной инъекции (для разных контекстов)? – Ben