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

时间:2014-03-13 11:07:47

标签: java dependency-injection cdi jboss-weld

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

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

如何使用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();
        }
    }

}

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

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

修改

目前我从AlgorithmState获得了AlgorithmExecutor,但是这会弄乱模型,我想避免这种情况。

1 个答案:

答案 0 :(得分:3)

首先,@New限定符已替换为@Dependant范围,无论如何都是默认范围。我想,由于它引起的混乱,它在CDI 1.1中发生了变化。另外,@New是一个限定符,而不是范围,并且来自可用于多种目的的单独标准(我认为@New并不是任何标准都使用的。)

您似乎希望在@Produces而不是AlgorithmState中使用@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注入Algorithm;从AlgorithmExecutor实例获取!事实上,如果你这样做,那就应该简单地解决整个问题。