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

tpu*_*nen 11 java ejb-3.0

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

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

Foo.java:

@Local
public interface FoO {
    public void doSomething();
    public void processWithNewTransaction(); // this should actually be private
}
Run Code Online (Sandbox Code Playgroud)

FooBean.java:

@Stateless
public class FooBean implements Foo {

    @EJB
    private Foo foo;

    public void doSomething() {
        ...
        foo.processWithNewTransaction();
        ...
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void processWithNewTransaction() {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我提取processWithNewTransaction()到另一个bean,它将需要在接口中作为公共方法公开,即使它只应该被调用FooBean.(同样的问题是我上面的代码,这就是接口定义中有注释的原因.)

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

小智 11

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


mic*_*nko 11

有可能做到self injection.你需要使用SessionContext.

SessionContext sc = ...
sc.getBusinessObject(FooBean.class).processWithNewTransaction()
Run Code Online (Sandbox Code Playgroud)


Kos*_*801 2

更新:正如其他答案所指出的,这在技术上确实是可能的。请参阅CsabaMichael的答案,了解尽管存在看似无限的递归,但它如何以及为何工作。


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

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

如果您需要单独的事务,我建议让事情变得简单并创建两个独立的 bean/接口。