Как создавать экземпляры "на лету" в 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, что делает его зависимым, и вы получите новый экземпляр каждый раз, когда он будет введен, и эти экземпляры не будут уничтожены до тех пор, пока уничтожающий экземпляр не будет уничтожен.