Несколько экземпляров с отслеживанием состояния объекта EJB при введении через КДИ
Речь идет в основном о понимании различий при введении статусного EJB
(SFSB
) с @Inject
по сравнению с инъекцией его с @EJB
.
@Inject
. Таким образом, мое предположение состояло в том, что если я создам два @RequestScoped
Боба и введу в каждый SFSB
дважды (один раз с @Inject
, один раз с @EJB
), SFSB
, введенный через @Inject
, будет одним и тем же экземпляром в обоих @RequestScoped
бобы , тогда как те, которые вводятся через @EJB
, будут различными экземплярами.
Это предположение кажется неправильным, но я не понимаю, почему. Не следует ли CDI
осознавать тот факт, что оба Боба являются @RequestScoped
и, следовательно, вводят один и тот же SFSB
? Почему это не так, или мой тестовый код несколько испорчен?
Это мой SFSB
и его интерфейс:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Local;
import javax.ejb.PrePassivate;
import javax.ejb.Stateful;
import package.MyStateful;
@Stateful
@Local(MyStateful.class)
public class MyStatefulImpl implements MyStateful {
@PostConstruct
private void postConstruct() {
System.out.println("SFSB postconstruct ref: " + this.toString());
}
@PreDestroy
private void preDestroy() {
System.out.println("SFSB predestroy ref: " + this.toString());
}
@PrePassivate
private void prePassivate() {
System.out.println("SFSB prepassivate ref: " + this.toString());
}
@Override
public String myToString() {
return toString();
}
}
public interface MyStateful {
String myToString();
}
А это один @RequestScoped
Боб:
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import package.MyStateful;
@Named
@RequestScoped
public class MyFirstRequestScoped {
@Inject
MyStateful myStatefulByCDI;
@EJB
MyStateful myStatefulByEJB;
public MyStateful getMyStatefulByCDI() {
System.out.println("first#myStatefulByCDI proxy ref: " + myStatefulByCDI.toString());
System.out.println("first#myStatefulByCDI stateful ref: " + myStatefulByCDI.myToString());
return myStatefulByCDI;
}
public MyStateful getMyStatefulByEJB() {
System.out.println("first#myStatefulByEJB proxy ref: " + myStatefulByEJB.toString());
System.out.println("first#myStatefulByEJB stateful ref: " + myStatefulByEJB.myToString());
return myStatefulByEJB;
}
}
Есть еще один @RequestScoped
боб с именем MySecondRequestScoped
и аналогичная реализация.
Когда они вызываются со страницы JSF
xhtml через EL
(ничего особенного, просто <h:outputText value="#{myFirstRequestScoped.myStatefulByCDI}" />
и так далее, чтобы вызвать их создание), это вывод консоли (WebSphere ApplicationServer 8.5.5.0):
[1/4/14 12:39:11:759 CET] 000000dc SystemOut O SFSB postconstruct ref: package.MyStatefulImpl@c03fcdee
[1/4/14 12:39:11:761 CET] 000000dc SystemOut O SFSB postconstruct ref: package.MyStatefulImpl@36b3bb10
[1/4/14 12:39:11:761 CET] 000000dc SystemOut O first#myStatefulByCDI proxy ref: package.EJSLocal0SFMyStatefulImpl_8d170245@48da7f98(BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA11-0143-4000-E000-6A007F000001))
[1/4/14 12:39:11:762 CET] 000000dc SystemOut O first#myStatefulByCDI stateful ref: package.MyStatefulImpl@36b3bb10
[1/4/14 12:39:11:768 CET] 000000dc SystemOut O SFSB postconstruct ref: package.MyStatefulImpl@9b3971c7
[1/4/14 12:39:11:768 CET] 000000dc SystemOut O SFSB postconstruct ref: package.MyStatefulImpl@456cec27
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O second#myStatefulByCDI proxy ref: package.EJSLocal0SFMyStatefulImpl_8d170245@48da7fa1(BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA18-0143-4000-E001-6A007F000001))
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O second#myStatefulByCDI stateful ref: package.MyStatefulImpl@456cec27
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O first#myStatefulByEJB proxy ref: package.EJSLocal0SFMyStatefulImpl_8d170245@48da7f9b(BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA0E-0143-4000-E000-6A007F000001))
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O first#myStatefulByEJB stateful ref: package.MyStatefulImpl@c03fcdee
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O second#myStatefulByEJB proxy ref: package.EJSLocal0SFMyStatefulImpl_8d170245@48da7fa1(BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA18-0143-4000-E000-6A007F000001))
[1/4/14 12:39:11:770 CET] 000000dc SystemOut O second#myStatefulByEJB stateful ref: package.MyStatefulImpl@9b3971c7
[1/4/14 12:39:11:848 CET] 000000dc SystemOut O SFSB predestroy ref: package.MyStatefulImpl@36b3bb10
[1/4/14 12:39:11:849 CET] 000000dc SystemOut O SFSB predestroy ref: package.MyStatefulImpl@456cec27
[1/4/14 12:50:11:765 CET] 00000120 SystemOut O SFSB prepassivate ref: package.MyStatefulImpl@c03fcdee
[1/4/14 12:50:11:766 CET] 00000120 SystemOut O SFSB prepassivate ref: package.MyStatefulImpl@9b3971c7
Итак, кажется, что:
-
созданы 4 экземпляра SFSB ; я ожидал бы, что это будет всего 3. Те, кто вводится через
@EJB
, не знают контекста, поэтому я бы подумал, что это нормально, если они создано для каждой точки впрыска. Но посколькуCDI
должен быть осведомлен о контексте (@RequestScoped
), я подумал, чтоCDI
будет повторно проецировать уже созданныйSFSB
. - единственное различие между
@Inject
и@EJB
, по-видимому, заключается в том, что жизненный цикл автоматически управляется при введении черезCDI
- метод с аннотацией@PreDestroy
называется для тех (36b3bb10 и 456cec27). Они вводятся через@EJB
(c03fcdee и 9b3971c7) позже только пассивируются и, кажется, не разрушаются в любое время позже.
@Inject
вместо @EJB
, но я не понимаю, что на самом деле подразумевается под контекстуальным осознанием CDI
, Когда есть новый экземпляр SFSB
, созданный независимо от области видимости?
Кстати, то же самое происходит и при использовании @SessionScoped
бобы, даже если второй Боб создан после перехода по ссылке на другую страницу (чтобы убедиться, что SFSB
, введенный через @Inject
, определенно существует уже). Более того, SFSB
экземпляры , вводимые через @EJB
, создаются только один раз в течение всего времени сеанса, так же как и те, которые вводятся через @Inject
- так что они, похоже, тоже каким-то образом осознают контекст...? При смешивании @SessionScoped
и @RequestScoped
бобов, Боб @SessionScoped
получает другой экземпляр SFSB
инъецируется, чем @RequestScoped
боб, что прекрасно , но, похоже, не является особенностью CDI, так как это верно для обоих тех экземпляров SFSB
вводится через @Inject
, а также для тех, кто вводится через @EJB
.
Редактировать: вывод наблюдаемого поведения:
Единственное различие между введением SFSB
через @Inject
и @EJB
, по-видимому, состоит в том, что в первом случае SFSB
автоматически уничтожается, когда область остается, а во втором-нет. Это правильно? Это показалось бы мне странным, так как я ожидал, что CDI
будет вести себя иначе...
Любые намеки на то, что я упускаю, т. е. непонимание, когда это доходит до "С" в "CDI
"? Надеюсь, это не какая-то там "специальность"...
1 ответ:
Для того, чтобы ваш SFSB был ограничен запросом, вам нужно дать ему область
@RequestScoped
. Затем вы должны увидеть, как вводится тот же экземпляр. Теперь, поскольку оба они являются прокси, самый простой способ подтвердить-установить некоторое значение из одного Боба и получить значение из другого Боба.