与使用EJB
注入有状态SFSB
(@Inject
)相比,这主要是为了理解差异。
通过@EJB
注入时,主要区别之一应该是上下文意识。所以我的假设是,如果我创建了两个@Inject
bean并且每个@RequestScoped
两次(一次使用SFSB
,一次使用@Inject
) ,通过@EJB
注入的SFSB
将是@Inject
bean 中的相同实例,而通过@RequestScoped
注入的实例将是不同的实例。
这个假设似乎是错误的,但我不明白为什么。 @EJB
不应该意识到两个bean都是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();
}
bean:
@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;
}
}
的{{1}} bean具有类似的实现。
当从@RequestScoped
xhtml页面通过MySecondRequestScoped
调用它们时(没有什么特别的,只有JSF
等等来触发它们的创建),这是控制台输出(WebSphere ApplicationServer) 8.5.5.0):
EL
所以看来:
<h:outputText value="#{myFirstRequestScoped.myStatefulByCDI}" />
注入的人不知道上下文,所以我认为如果为每个注入点创建它们都没关系。但由于[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
应该知道上下文(@EJB
),我认为CDI
会重新注入已创建的@RequestScoped
。CDI
和SFSB
之间的唯一区别似乎在于,通过@Inject
注入后,生命周期会自动管理 - 注释 @EJB
的方法被称为那些(36b3bb10和456cec27)。通过CDI
(c03fcdee和9b3971c7)注入的这些内容后来才被钝化,似乎以后不会被破坏。后者似乎是使用@PreDestroy
代替@EJB
的一个很好的理由,但我不明白的是{{1} {strong}的上下文意识的真正意义} ,当创建@Inject
的新实例时,无论范围如何?
顺便说一下,当使用 @EJB
bean时,这种行为相同,即使第二个bean是在跟踪到另一个页面的链接后创建的(为了确保{{1}通过CDI
注入肯定已存在)。此外,通过SFSB
注入的@SessionScoped
个实例只会在会话的生命周期内创建一次,就像通过SFSB
注入的实例一样 - 所以这些似乎不知怎的,要注意上下文......?在混合@Inject
和SFSB
bean时,@EJB
bean会获得注入的@Inject
的另一个实例,而不是@SessionScoped
bean很好 - 但这似乎不是CDI的一个特征,因为对于两者通过@RequestScoped
注入的@SessionScoped
的那些实例以及注入的那些实例都是如此通过SFSB
。
编辑:观察到的行为的结论:
通过@RequestScoped
和SFSB
注入@Inject
之间的唯一区别似乎是,在前一种情况下,@EJB
会在保留范围时自动销毁,在后一种情况下不是。它是否正确?这会让我感到奇怪,因为我期望SFSB
行为不同......
关于我缺少什么的任何提示,即对“@Inject
”中的“C”的误解?我希望它不是某些WebSphere“专业”......
答案 0 :(得分:3)
为了使您的SFSB成为请求的范围,您需要为其提供@RequestScoped
范围。然后你应该看到注入相同的实例。既然这两个都是代理的,最简单的确认方法是从一个bean设置一些值,并从另一个bean获取值。