Как создавать экземпляры "на лету" в CDI

Предположим, что у меня класс Car. В моем коде я хочу создать 10 автомобилей. Класс Car имеет некоторые аннотированные зависимости @Inject. Какой был бы лучший способ сделать это?

У CDI есть интерфейс провайдера, который я могу использовать для создания автомобилей:

@Inject Provider<Car> carProvider;
public void businessMethod(){
    Car car = carProvider.get();
}

К сожалению, это не работает, если у меня нет CarFactory, у которого есть метод с аннотацией @Produces, который создает автомобиль. Насколько он отражает реальный мир, что я не могу создавать автомобили без factory, я бы предпочел не писать заводы для всего. Я просто хочу, чтобы контейнер CDI создавал мою машину, как и любой другой bean. Как вы рекомендуете создавать эти автомобили?

Ответ 1

Просто используйте интерфейс javax.enterprise.inject.Instance.

Вот так:

public class Bean {

    private Instance<Car> carInstances;

    @Inject
    Bean(@Any Instance<Car> carInstances){
        this.carInstances = carInstances;
    }

    public void use(){
        Car newCar = carInstances.get();
        // Do stuff with car ...
    }

}

Ответ 2

Моей любимой моделью для программного поиска является использование CDI.current().select().get().

Продемонстрировано здесь.

Сервлет имеет зависимость от двух CDI beans, области с одним запросом и другого приложения:

private final RequestScopedBean requestScoped
            = CDI.current().select(RequestScopedBean.class).get();

private final ApplicationScopedBean applicationScoped
            = CDI.current().select(ApplicationScopedBean.class).get();

Тестовый класс, который использует этот сервлет, можно найти здесь.

Изучите код, и вы заметите, что код полностью эквивалентен тому, что вы получите с помощью @Inject MyBean myBean;.

Ответ 3

Вы можете использовать квалификаторы с аннотациями @Produces:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
public @interface MyCars {
}

Пример-производитель-метод:

@Produces
@MyCars
public Car getNewCar(@New Car car){
    return car;
}

использование:

@Inject
@MyCars
private Provider<Car> carProvider;

Ответ 4

Другим способом сделать это было бы просто не дать Car какой-либо области CDI, что делает его зависимым, и вы получите новый экземпляр каждый раз, когда он будет введен, и эти экземпляры не будут уничтожены до тех пор, пока уничтожающий экземпляр не будет уничтожен.