Ссылка на компонент CDI в неуправляемом компоненте CDI
Можно ли получить экземпляр компонента CDI внутри класса, созданного с использованием new
ключевое слово? В настоящее время мы вносим некоторые улучшения в старое приложение, и мы всегда получаем исключение ContextNotActiveException каждый раз, когда выполняем программный поиск компонентов CDI Singleton в нашем приложении.
Код для получения ссылки:
public class ClassCreatedWithNew{
public void doSomething(){
MySingletonBean myBean = BeanManagerSupport.getInstance().getBean(MySingletonBean.class);
}
}
BeanManagerSupport.java
public class BeanManagerSupport {
private static final Logger LOG = Logger.getLogger(BeanManagerSupport.class);
private static final BeanManagerSupport beanManagerSupport = new BeanManagerSupport();
private BeanManager beanManager;
private BeanManagerSupport() {
try {
beanManager = InitialContext.doLookup("java:comp/BeanManager");
} catch (NamingException e) {
LOG.error("An error has occured while obtaining an instance of BeanManager", e);
}
}
@SuppressWarnings("unchecked")
public <T> T getBean(Class<T> clazz) {
Iterator<Bean< ? >> iter = beanManager.getBeans(clazz).iterator();
if (!iter.hasNext()) {
throw new IllegalStateException("CDI BeanManager cannot find an instance of requested type " + clazz.getName());
}
Bean<T> bean = (Bean<T>) iter.next();
return (T) beanManager.getContext(bean.getScope()).get(bean);
}
public static BeanManagerSupport getInstance(){
return beanManagerSupport;
}
}
2 ответа
Есть 2 возможных решения.
Если у вас есть контейнер JavaEE-7, вы можете использовать
CDI.current().get(MySingletonClass.class);
Если у вас есть контейнер JavaEE-6 или даже приложение Java SE, вы можете использовать Apache DeltaSpike BeanProvider. Он пытается найти BeanManager из JNDI, но также выполняет другие приемы, которые также работают, если у вас нет полного контейнера EE. Например, в SE и модульный тест.
Вы также должны позаботиться о том, чтобы загружался не только контейнер, но и чтобы контексты действительно активировались. Обычно это делается через ServletListener. Если вы находитесь в контейнере EE, они регистрируют его для вас. Если вы используете обычный кот, причал и т. Д., То вам нужно активировать его самостоятельно.
Посмотрите этот пример из Apache OpenWebBeans.
если вы используете new, вам необходимо иметь конструктор и вручную инициализировать зависимости и любую логику, которая от них зависит, в методе @PostConstruct. Вместо этого вы можете использовать CDI.current(), например
MyService service = CDI.current().select(MyService.class).get();
тогда вы сможете вызвать все свои методы службы.