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方法,那么每次迭代的事务要比所有迭代更好。 (提供的业务逻辑不是“全有或全无”,如发送交货或发行股票)