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

时间:2009-03-11 08:00:54

标签: java ejb-3.0

是否可以“自我注入”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来管理自己的事务,并且会为所有方法添加大量的样板。

5 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:11)

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

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

答案 2 :(得分:2)

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


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

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

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

答案 3 :(得分:2)

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

正如您必须在循环内调用本地bean方法的示例一样,每次迭代的事务比在所有迭代中更好。 (提供的业务逻辑不是全部或全部"如发送交货或发行股票)

答案 4 :(得分:1)

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

编辑:修正错别字