使用CDI在运行时创建和连接相关实例

pal*_*int 6 java dependency-injection cdi jboss-weld

我有一个ServiceJava SE应用程序(没有任何应用程序服务器),它创建Algorithm实例并运行它们.

  • 每个Algorithm实例都需要一个新的(单独的)ActionExecutor和一个新的(单独的)AlgorithmState.
  • ActionExecutor还需要一个AlgorithmState实例,这个实例必须和Algorithmgets一样.

我怎样才能用CDI实现这一目标?我已经尝试过构造函数注入和@New两个参数,Algorithm但我想这不是我想要的.

Service 类:

import java.util.ArrayList;
import java.util.List;

import javax.enterprise.inject.Instance;
import javax.inject.Inject;

public class Service {

    @Inject
    private Instance<Algorithm> algorithmInstance;

    public void run() {
        final List<Algorithm> algorithms = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            final Algorithm algorithm = algorithmInstance.get();
            algorithms.add(algorithm);
        }

        for (final Algorithm algorithm: algorithms) {
            algorithm.doSomething();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

Algorithm 类:

import java.util.concurrent.atomic.AtomicInteger;

import javax.enterprise.inject.New;
import javax.inject.Inject;

public class Algorithm {

    private static final AtomicInteger counter = new AtomicInteger(100);

    private final ActionExecutor actionExecutor;
    private final AlgorithmState algorithmState;

    private final int id;

    @Inject
    public Algorithm(@New final ActionExecutor actionExecutor, @New final AlgorithmState algorithmState) {
        this.actionExecutor = actionExecutor;
        this.algorithmState = algorithmState;
        id = counter.incrementAndGet();
        System.out.println("algorithm ctor#" + id);
    }

    public void doSomething() {
            System.out.printf("do something, algorithm id: #%d: executor id%sd, stateId: %d, executor->stateId: %d%n", id,
            actionExecutor.getId(), algorithmState.getId(), actionExecutor.getAlgorithmStateId());
    }
}
Run Code Online (Sandbox Code Playgroud)

ActionExecutor 类:

import java.util.concurrent.atomic.AtomicInteger;

import javax.inject.Inject;

public class ActionExecutor {

    private static AtomicInteger counter = new AtomicInteger(200);

    private final AlgorithmState algorithmState;

    private final int id;

    @Inject
    public ActionExecutor(final AlgorithmState algorithmState) {
        this.algorithmState = algorithmState;
        id = counter.incrementAndGet();
    }

    public int getId() {
        return id;
    }

    public int getAlgorithmStateId() {
        return algorithmState.getId();
    }
}
Run Code Online (Sandbox Code Playgroud)

AlgorithmState 类:

import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

public class AlgorithmState {

    private static final AtomicInteger counter = new AtomicInteger(300);

    private final int id;

    @Inject
    public AlgorithmState() {
        id = counter.incrementAndGet();
    }

    @PostConstruct
    public void start() {
        System.out.println("state start#" + id);
    }

    public int getId() {
        return id;
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个ServiceMain测试类:

import java.util.List;

import javax.enterprise.event.Observes;
import javax.inject.Inject;

import org.jboss.weld.environment.se.bindings.Parameters;
import org.jboss.weld.environment.se.events.ContainerInitialized;

public class ServiceMain {

    @Inject
    private Service service;

    public void printHello(
            @Observes final ContainerInitialized event,
            @Parameters final List<String> parameters) {
        System.out.println("ServiceMain:" + service);
        service.run();
    }

    public static void main(final String[] args) {
        org.jboss.weld.environment.se.StartMain.main(args);
    }

}
Run Code Online (Sandbox Code Playgroud)

目前它打印以下内容:

do something, algorithm id: #101: executor id201d, stateId: 302, executor->stateId: 301
do something, algorithm id: #102: executor id202d, stateId: 304, executor->stateId: 303
do something, algorithm id: #103: executor id203d, stateId: 306, executor->stateId: 305
Run Code Online (Sandbox Code Playgroud)

我需要的是,stateId并且executor->stateId是相同的:

do something, algorithm id: #101: executor id201d, stateId: 301, executor->stateId: 301
do something, algorithm id: #102: executor id202d, stateId: 302, executor->stateId: 302
do something, algorithm id: #103: executor id203d, stateId: 303, executor->stateId: 303
Run Code Online (Sandbox Code Playgroud)

编辑:

目前我AlgorithmState从中得到了AlgorithmExecutor它但它弄乱了模型,我想避免这种情况.

Mat*_*att 3

首先,@New限定符被替换为@Dependant范围,无论如何它都是默认范围。我想它在 CDI 1.1 中被改变了,因为它造成了混乱。另外,@New是一个限定符,而不是范围,并且来自一个可用于多种目的的单独标准(我认为@New任何标准都没有真正使用它)。

看来您想使用@ProducesinAlgorithmState而不是@Inject. 查看有关该主题的 Weld 文档以了解更多详细信息。您可能想要创建一个特定的作用域类型,如下所示:

@ScopeType
@Retention(RUNTIME)
@Target({TYPE, METHOD, CONSTRUCTOR})
public @interface AlgorithmScoped {}
Run Code Online (Sandbox Code Playgroud)

然后你可以修改AlgorithmState构造函数:

@Produces @AlgorithmScoped
public AlgorithmState() {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

将该范围添加到AlgorithmExecutor,然后也添加到Algorithm。我认为你不应该尝试AlgorithmState注入Algorithm; 从实例中获取它AlgorithmExecutor!事实上,如果你这样做,那么简而言之应该可以解决整个问题。