Несколько экземпляров с отслеживанием состояния объекта 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. Затем вы должны увидеть, как вводится тот же экземпляр. Теперь, поскольку оба они являются прокси, самый простой способ подтвердить-установить некоторое значение из одного Боба и получить значение из другого Боба.