14

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

4

5 回答 5

13

可以做一个self injection. 你需要使用SessionContext.

SessionContext sc = ...
sc.getBusinessObject(FooBean.class).processWithNewTransaction()
于 2013-01-05T12:59:16.990 回答
11

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

于 2012-09-04T01:24:05.123 回答
2

更新:正如其他答案所指出的,这在技术上确实是可行的。请参阅CsabaMichael的答案,了解它如何以及为什么会在看似无休止的递归的情况下起作用。


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

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

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

于 2009-03-11T10:39:25.757 回答
2

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

就像示例一样,如果您必须在循环中调用本地 bean 方法,那么每次迭代都有一个事务比所有迭代都要好。(前提是业务逻辑不是像发货或发行股票那样“全有或全无”)

于 2011-07-29T11:28:34.773 回答
1

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

编辑:修正错别字

于 2009-03-13T00:21:24.030 回答