通过CDI注入时有状态EJB的多个实例

时间:2014-01-04 13:27:04

标签: dependency-injection java-ee-6 cdi ejb-3.1 websphere-8

与使用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

所以看来:

  • 创建了4个SFSB实例;我本以为只有3 。那些通过<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
  • CDISFSB之间的唯一区别似乎在于,通过@Inject注入后,生命周期会自动管理 - 注释 @EJB的方法被称为那些(36b3bb10和456cec27)。通过CDI(c03fcdee和9b3971c7)注入的这些内容后来才被钝化,似乎以后不会被破坏。

后者似乎是使用@PreDestroy代替@EJB的一个很好的理由,但我不明白的是{{1} {strong}的上下文意识的真正意义} ,当创建@Inject的新实例时,无论范围如何?

顺便说一下,当使用 @EJB bean时,这种行为相同,即使第二个bean是在跟踪到另一个页面的链接后创建的(为了确保{{1}通过CDI注入肯定已存在)。此外,通过SFSB注入的@SessionScoped个实例只会在会话的生命周期内创建一次,就像通过SFSB注入的实例一样 - 所以这些似乎不知怎的,要注意上下文......?在混合@InjectSFSB bean时,@EJB bean会获得注入的@Inject 的另一个实例,而不是@SessionScoped bean很好 - 但这似乎不是CDI的一个特征,因为对于两者通过@RequestScoped注入的@SessionScoped的那些实例以及注入的那些实例都是如此通过SFSB

编辑:观察到的行为的结论: 通过@RequestScopedSFSB注入@Inject之间的唯一区别似乎是,在前一种情况下,@EJB会在保留范围时自动销毁,在后一种情况下不是。它是否正确?这会让我感到奇怪,因为我期望SFSB行为不同......

关于我缺少什么的任何提示,即对“@Inject”中的“C”的误解?我希望它不是某些WebSphere“专业”......

1 个答案:

答案 0 :(得分:3)

为了使您的SFSB成为请求的范围,您需要为其提供@RequestScoped范围。然后你应该看到注入相同的实例。既然这两个都是代理的,最简单的确认方法是从一个bean设置一些值,并从另一个bean获取值。