При внедрении ConfigProperty получение нулевого значения в конструкторе, с @Inject или без него над конструктором?

Для Хелидон МП..

Я наблюдаю некоторую проблему при внедрении поля при доступе в конструкторе.

В приведенном ниже сценарии получение нулевого значения в конструкторе с @Inject или без него над конструктором

Класс GreetingProvider снабжен аннотацией ApplicationScoped

@Inject
@ConfigProperty(name = "app.greeting")
private String message;

@Inject //Getting the field as null with or without @Inject annotation
public GreetingProvider() {   
  LOG.debug("Message {}, message);
}

Может получить значение в прослушивателе событий для ApplicationScoped.

Он отлично работает, если я использовал инъекцию на основе конструктора.

@Inject
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {   
    this.message.set(message);
}

Разве конструктор не должен получать инициализированное значение из инъекции поля?

Ожидается, что инициализированное поле, введенное с помощью @ConfigProperty, будет доступно в конструкторе.

Он доступен в методе, аннотированном @PostConstruct, или в методе, который наблюдает за событием activated(@Observes @Initialized(ApplicationScoped.class) final Object event).

Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Лучшие практики использования Guice в ваших Java-проектах
Лучшие практики использования Guice в ваших Java-проектах
Guice от Google - это популярная система инъекции зависимостей для Java-приложений. Он помогает разработчикам создавать более ремонтопригодный,...
4
0
121
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Значения полей можно вводить только после создания экземпляра объекта. Создание экземпляра объекта требует вызова конструктора. Итак, если вы думаете об этом, ваш конструктор по умолчанию вызывается для создания экземпляра объекта в первую очередь, и только после построения поля вводятся в том порядке, в котором они объявлены. Вот почему все поля @Inject будут нулевыми при доступе к ним через конструктор по умолчанию.

Правильный способ справиться с этой ситуацией - через внедрение конструктора, используя @Inject в конструкторе, как во втором примере.

@Inject
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {   
    this.message.set(message);
}

Здесь вы определяете зависимости, необходимые вашему классу, а диспетчер CDI гарантирует, что зависимости будут переданы в конструктор с аннотацией @Inject. Теперь вы можете обращаться к зависимостям как к формальным аргументам конструктора и самостоятельно инициализировать поля.

Метод с аннотацией @PostConstruct OTOH вызывается только один раз для каждого экземпляра и после завершения внедрения конструктора, поля и метода. Если у вас есть какая-то логика, которая должна выполняться один раз для каждого экземпляра, @PostConstruct — идеальный способ.

@PostConstruct
public void executeOncePerInstance(){
   // You can safely access all the field & constructor-injected properties here 
}

Поведение будет похоже на внедрение конструктора, но некоторые реализации контейнера CDI могут вызывать конструктор более одного раза в процессе настройки прокси-сервера Java для компонента.

Спасибо за подробное разъяснение. Кроме того, еще одна вещь, которую следует добавить после просмотра документов CDI, это то, что по умолчанию его ленивая инициализация, поэтому для класса контроллера (те, которые предоставляют API REST, но никогда не внедряются) лучше использовать наблюдение за событиями@Observes @Initialized(ApplicationScoped.class...), так как @PostConstruct может вызываться только после того, как bean-компонент введен в первый раз.

SidM 04.04.2023 11:42

Другие вопросы по теме

Похожие вопросы

Метод вызова после инициализации компонента, но до вызова @Bean
«Должен быть установлен ServiceLocationProvider» в коллекции сервисов DI .net core
Каков предпочтительный способ хранения экземпляра объекта, похожего на сервис, в Dancer2, к которому могут получить доступ методы маршрутов модуля?
ASP.NET Core — использование ограниченной службы в фоновом задании
Не удается получить доступ к вложенной функции из другого файла в javascript
Перехватывать все экземпляры с помощью Simple Injector
Угловая инъекция зависимости — игнорировать, если она не указана — вариант использования: MAT_DIALOG_DATA
Вызов WPF SimpleInjector для client.GetAsync зависает
Есть ли способ разрешить службу, внедренную зависимостями, в модель ASPNET Core MVC только с конструктором по умолчанию?
Служба .net6 IServiceProvider, зарегистрированная в сборке, загруженной во время выполнения, не разрешена основной сборкой (части приложения)