"non-managed" 实用程序 class 的并发访问和扩展

Concurrent access and scaling of "non-managed" utility class

如果我有一个有状态 class 需要类似实用程序的无状态 class 来对其执行操作。这些有状态 classes 保存在容器(有状态)class 的列表中。这就是我对普通 Java:

所做的
class Container {
    List<Stateful> sfList;
}

class Stateful {

    List<String> list;

    void someMethod() {
        list.add("SF");
        Stateless.foo(this);
}

class Stateless {
    public static void foo(Stateful sf) {
        sf.getList().add("SL");
    }
}

main里面是这样的过程:

Stateful sf = new Stateful();
sfList.add(sf);
sf.someMethod();

现在使用 JavaEE CDI 我会做:

class StatefulBean {

    List<String> list;

    @Inject
    StatelessBean slsb;

    void someMethod() {
        list.add("SF");
        slsb.add(this);
}

@Stateless
class StatelessBean {
    public void add(StatefulBean sfsb) {
        sfsb.add("SL");
    }
}

在这种情况下,所有 StatefulBean 都可以访问 StatelessBean 的共享池而不会出现并发问题,并且它将根据请求进行适当扩展。

但是,由于 Stateful 不是托管 bean,我无法注入它,所以我改用了实用程序 class。此外,我正在使用构造函数创建 Stateful,因此我无法将无状态 bean 注入其中(我将使用它获得 NPE)。

我的问题是:

Are there concurrency and scalabilty differences between the stateless injection approach (provided it would work) and the utility class approach?

是的,主要是围绕管理的损失。在每次调用该方法时实例化 Stateful 的方式不涉及池化。这将导致您创建比您可能需要的更多的实例。

另一个损失是在可伸缩性方面。在容器将管理分布式环境中有状态 bean 的钝化和激活的地方,手动方法将确保您管理自己的激活和钝化。

Since Stateful is not a managed bean..

不正确。根据 CDI Spec,任何满足所列条件的 java class(在您的情况下,默认的无参数构造函数)都是托管 bean。这意味着您可以 @Inject StatelessBeanStateless 并且容器将有义务。要允许此级别的管理,您需要在 beans.xml.

中设置 bean-discovery-mode=all

即使使用(显然不必要的)循环引用,正常的 Java 并发规则也适用:只要您正在操作的状态不是静态的或处于静态 class,您重新线程安全。对该静态方法的每个线程调用仍然在单独的堆栈上运行,因此没有问题。

How can I make the EE injection approach work? If you need on-demand instantiation of Stateless(or any other bean really), use the CDI Instance to programmatically obtain a managed instance of any class you want. You can now add something like this to Container:

@Inject @Dependent Instance<Stateful> stateful;

    @PostConstruct
     public void createStateless(){
         //instantiate sfList;
         sfList.add(stateful.get()); //execute as many times as you need
     }