#jakarta-ee #ejb
#джакарта-ee #ejb
Вопрос:
Вопрос новичка: могу ли я в любом случае вводить разные компоненты на основе условия, которое я установил в файле свойств. Вот чего я хочу добиться:
Я установил некоторое значение в файле свойств. Если это правда, то я хочу
public class MyClass{
@EJB
private MyBean bean;
}
если оно равно false, то
public class MyClass{
@EJB
private MyBean2 bean2;
}
Выполнимо ли это?
Комментарии:
1. Выполнение поиска JNDI было бы жизнеспособной альтернативой, дающей то же постусловие, но перенос вашего кода между серверами приложений будет затруднен, поскольку путь JNDI по умолчанию к EJBS не стандартизирован.
Ответ №1:
Как сказал Гонсало, вам сначала нужно будет указать общий интерфейс компонента, если вы хотите объявить его как поле класса и использовать разные его реализации.
Более того, я думаю, вы могли бы сделать его более элегантным, используя метод CDI @Products; т.Е. несколько между этими строками:
@Singleton
@Startup
public class Configuration {
private boolean someCondition;
@PostConstruct
private void init() {
someCondition = ... // get a value from DB, JMS, XML, etc.
}
@EJB(lookup="java:comp/env/myParticularBean")
MyBean myBean1;
@EJB(beanName="anotherTypeOfBeanInjectedByName")
MyBean myBean2;
@Produces
public MyBean produceMyBean() {
if (someCondition)
return myBean1;
} else {
return myBean2;
}
}
}
Затем в вашем коде вы можете просто использовать:
@Inject
MyBean myBean;
и для вас будет введен соответствующий компонент, основанный на вашем условии.
Если вам не нужно поле на уровне класса, вы можете использовать старый способ и найти EJB в JNDI — таким образом, у вас есть контроль над тем, какой тип и какой компонент должен быть расположен и использоваться.
РЕДАКТИРОВАТЬ: я добавил @EJB
аннотированные компоненты, чтобы показать, откуда могут быть получены экземпляры ‘myBean1’ и ‘myBean2’.
Этот пример показывает, что у вас может быть одно-единственное место, где вы определяете все свои зависимости от различных реализаций EJB и других компонентов. В примере это может быть реализовано как одноэлементный EJB с полями @EJB, полями @PersistenceContext и т. Д.
Вместо того, чтобы делать это представленным способом, вы можете изменить return myBean1
что-то вроде return context.lookup("JNDI_NAMESPACE_COORDINATES")
where context
is экземпляр InitialContext
.
Надеюсь, это сделает его более понятным.
Комментарии:
1. спасибо за предложение. но я не совсем понимаю, как вернуть «myBean1» или «myBean2», когда возвращаемый тип «MyBean»? Не могли бы вы показать мне немного больше деталей?
2. myBean1 и myBean2 являются экземплярами классов, которые реализуют MyBean. Я обновлю вопрос, чтобы показать еще немного кода
3. Спасибо Педроковальски. итак, какой класс должен иметь метод «public MyBean produceMyBean ()»?
4. @neo все, что вам подходит 🙂 Это может быть одноэлементный EJB, если вы хотите использовать
@EJB
, как показано в примере. Это может быть обычный класс, если вы предпочитаете использовать поиск JNDI вручную.5. Спасибо и взгляните на пример — надеюсь, на этот раз все будет понятнее.
Ответ №2:
Я не думаю, что вы можете изменить тип вводимого компонента. Я бы сказал, что это ограничение Java, поскольку это строго типизированный язык 🙂
Однако у вас может быть сценарий, в котором несколько компонентов реализуют один и тот же интерфейс, и вы хотите внедрить конкретную реализацию этого интерфейса следующим образом:
@Local
public interface MyBean {
}
@Stateless
public class MyBeanImpl1 implements MyBean {
}
@Stateless
public class MyBeanImpl2 implements MyBean {
}
Тогда вы могли бы сделать:
public MyClass {
@EJB(beanName="MyBeanImpl1")
MyBean myBean;
}
или
public MyClass {
@EJB(beanName="MyBeanImpl2")
MyBean myBean;
}
В зависимости от реализации, которую вы хотите внедрить.
Комментарии:
1. Не самое лучшее решение, потому что, если вы решите изменить реализацию, вам придется перекомпилировать свой код.
2. На самом деле, @Neo запросил инъекции на основе условий. Не выбранные вручную инъекции.