EJB3 bean可以“自我注入”并通过EJB容器调用自己的方法吗?

是否可以“自我注入”EJB以便将本地方法作为bean方法调用? 在某些情况下,这可能是有利的,例如,如果使用容器管理的事务,并且应该在新事务中完成某些事务。

这是如何工作的一个例子:

Foo.java:

@Local public interface FoO { public void doSomething(); public void processWithNewTransaction(); // this should actually be private } 

FooBean.java:

 @Stateless public class FooBean implements Foo { @EJB private Foo foo; public void doSomething() { ... foo.processWithNewTransaction(); ... } @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void processWithNewTransaction() { ... } } 

如果我将processWithNewTransaction()提取到另一个bean,它将需要在接口中作为公共方法公开,即使它只应由FooBean 。 (同样的问题在于我的代码,这就是为什么在接口定义中有注释。)

一种解决方案是切换到bean管理的事务。 但是,这需要更改整个bean来管理自己的事务,并且会为所有方法添加大量的样板。

更新 :如其他答案所述,这确实在技术上是可行的。 请看看Csaba和Michael的答案,尽管有无尽的递归,但它的工作方式和原因仍然存在。


我无法给出100%准确的答案,但我很确定这是不可能的。

我想是这样的,因为为了将Foo bean注入Foo bean本身,容器最初必须创建一个他可以随后注入的Foo实例。 但是为了创建它,他必须将已经存在的Foo实例注入到要创建的Foo中……这导致无限递归。

如果你需要单独的交易,我建议保持简单并创建两个独立的bean /接口。

自我注入EJB确实是可能的。 在这种情况下无法进行无限递归的原因非常简单:容器不会从池中注入实际的bean实例。 相反,它会注入一个代理对象。 当您在注入的代理(foo)上调用方法时,容器从其池中获取bean实例,或者如果没有可用实例则创建一个bean实例。

可以进行self injection 。 您需要使用SessionContext

 SessionContext sc = ... sc.getBusinessObject(FooBean.class).processWithNewTransaction() 

有趣的问题。 我从不在同一个bean中创建一个具有不同事务属性的方法,也就是说,这需要重构。 这通常使得在应用程序发展时很难发现应用程序中的错误。

编辑:修正错别字

我倾向于不同意,通常它对事务管理通过容器调用本地bean方法很有用。

正如作为示例,如果您必须在循环内调用本地bean方法,那么每次迭代的事务要比所有迭代更好。 (提供的业务逻辑不是“全有或全无”,如发送交货或发行股票)