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

标签 java dependency-injection cdi jboss-weld

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

  • 每个 Algorithm 实例都需要一个新的(单独的)ActionExecutor 和一个新的(单独的)AlgorithmState
  • ActionExecutor 还需要一个 AlgorithmState 实例,该实例必须与 Algorithm 获取的相同。

如何使用 CDI 实现这一目标?我已经在 Algorithm 的两个参数上尝试了构造函数注入(inject)和 @New,但我想这不是我想要的。

服务类:

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();
        }
    }

}

算法类:

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());
    }
}

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();
    }
}

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;
    }
}

还有一个用于测试的 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);
    }

}

目前它打印以下内容:

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

我需要的是 stateIdexecutor->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

编辑:

目前我正在从AlgorithmExecutor 获取AlgorithmState,但它弄乱了模型,我想避免这种情况。

最佳答案

首先,@New 限定符被替换为 @Dependant 作用域,这是默认作用域。我想它在 CDI 1.1 中由于它引起的困惑而被更改。另外,@New 是一个限定符,而不是一个范围,并且来自一个可用于多种用途的单独标准(我不认为 @New 真的被使用了按任何标准)。

看起来您想在 AlgorithmState 中使用 @Produces 而不是 @Inject。查看Weld documentation on the subject了解更多详情。您可能想要创建一个特定的 scoped type像这样:

@ScopeType
@Retention(RUNTIME)
@Target({TYPE, METHOD, CONSTRUCTOR})
public @interface AlgorithmScoped {}

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

@Produces @AlgorithmScoped
public AlgorithmState() {
    // ...
}

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

关于java - 使用 CDI 在运行时创建和连接相关实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22376673/

相关文章:

java - 在Java图片中查找图片?

java - Spring 错误 : BeanNotOfRequiredTypeException

javascript - 用于可配置依赖注入(inject)的 RequireJS 依赖覆盖

.net - 在 Windsor 中注册通用装饰器

java - 使用CDI登录,@Produces返回缓存值

java - java中的业务数据验证方法

java - com.google.gson.stream.MalformedJsonException

java - 在迭代时将项目添加到链表是否安全

java - 如何序列化注入(inject)的bean?

java - 在 Weld 中使用@EJB 作为注入(inject)注解