Это в основном о понимании различий при введении запоминания состояния EJB
(SFSB
) с @Inject
по сравнению с впрыскиванием с @EJB
.Несколько экземпляров с учетом состояния 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: [email protected]
[1/4/14 12:39:11:761 CET] 000000dc SystemOut O SFSB postconstruct ref: [email protected]
[1/4/14 12:39:11:761 CET] 000000dc SystemOut O first#myStatefulByCDI proxy ref: [email protected](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: [email protected]
[1/4/14 12:39:11:768 CET] 000000dc SystemOut O SFSB postconstruct ref: [email protected]
[1/4/14 12:39:11:768 CET] 000000dc SystemOut O SFSB postconstruct ref: [email protected]
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O second#myStatefulByCDI proxy ref: [email protected](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: [email protected]
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O first#myStatefulByEJB proxy ref: [email protected](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: [email protected]
[1/4/14 12:39:11:769 CET] 000000dc SystemOut O second#myStatefulByEJB proxy ref: [email protected](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: [email protected]
[1/4/14 12:39:11:848 CET] 000000dc SystemOut O SFSB predestroy ref: [email protected]
[1/4/14 12:39:11:849 CET] 000000dc SystemOut O SFSB predestroy ref: [email protected]
[1/4/14 12:50:11:765 CET] 00000120 SystemOut O SFSB prepassivate ref: [email protected]
[1/4/14 12:50:11:766 CET] 00000120 SystemOut O SFSB prepassivate ref: [email protected]
Так что, похоже, что:
- 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
боба, который прекрасно - но, кажется, не особенность КДИ как-то, так как это верно для как тех случаи, от SFSB
, вводимого через @Inject
, а также для инъекций через @EJB
.
Edit: Вывод наблюдаемого поведения: Единственное различие между нагнетание SFSB
через @Inject
и @EJB
, кажется, что в первом случае SFSB
автоматически уничтожается, когда сфера остается и в последнем случае это не. Это верно? Это может показаться мне странным, так как я ожидал, что CDI
будет вести себя по-другому ...
Какие-либо намеки на то, что мне не хватает, т. Е. Недоразумение, когда дело доходит до "C" в категории "CDI
"? Я надеюсь, что это не какая-то «специальность» WebSphere ...
'@ EJB', кажется, исходит из другой эпохи технологий, чем CDI. Помимо всего прочего, для поиска используется JNDI. –
Несомненно, '@ EJB' существует гораздо дольше, чем' CDI', который является частью Java EE с версии 6 (см. Http://www.oracle.com/technetwork/java/javaee/tech/javaee6technologies-1955512 .html). Но, к сожалению, для меня это не объясняет поведение, описанное выше. – stef77