Присвоение значения компонента в @PostConstruct

#java #jakarta-ee #ejb

#java #джакарта-ee #ejb

Вопрос:

В приведенном ниже примере мне нужно присвоить Bean2 атрибут Bean1. Атрибут является null (см. Ниже). Кроме того, «@PostConstruct Bean2» печатается перед «После присвоения».

Есть ли способ убедиться, что экземпляр Bean2 создан перед присвоением значения в Bean1?

 @Stateless
public class Bean1 {

    @Inject
    private Bean2 bean2;

    String x;

    @PostConstruct
    private void init() {
         x = "Some Value";
         System.out.println("Before assignment");
         bean2.setX(x);
         System.out.println("After assignment");
    }
}

@Stateless
public class Bean2 {

    private String x;

    public setX(String x) {
         this.x = x;
    }

    @PostConstruct
    private void init() {
        System.out.println("@PostConstruct Bean2");
        System.out.println(x);  // <-- x is null
    }
  }
  

Ответ №1:

Это ожидаемое поведение, основанное на том, как вы все настроили. x должно быть правильно установлено в Bean2 после развертывания всего ApplicationContext.

Чтобы понять, что происходит, обратите внимание, что Bean2 это зависимость для Bean1 . Это означает, что Spring не может создавать, Bean1 пока после Bean2 не будет создан. Таким образом, он создается Bean2 первым, и вы видите, что x в init() блоке null, потому что Bean1 он еще не был сконструирован, чтобы можно было установить его значение.

Позже, Bean1 будет сконструирован, его init() метод будет вызван, и значение для x в Bean2 будет правильно установлено. Но это происходит спустя долгое время после того, как Bean2 ‘s @PostConstruct уже завершено.

Комментарии:

1. Я не использую Spring, можете ли вы перефразировать свой ответ? Кроме того, как добиться передачи значения Bean1 в Bean2?

2.Независимо от используемой вами платформы внедрения зависимостей результат один и тот же. Как только все приложение будет запущено, значение для x будет правильным. Это просто не может быть корректным в Bean2 методе @PostConstruct , потому что этот метод может быть запущен только после Bean2 создания, но до Bean1 создания. Таким образом, он попадает в своего рода «мертвую зону», где код, который его инициализировал, еще не может быть запущен. Но этот код в конечном итоге будет запущен, и значение будет хорошим после запуска всего приложения.

3. Есть ли способ узнать в Bean1, что внедренный экземпляр Bean2 уже создан?

4. Вы знаете, что внутри Bean1 это Bean2 уже создано, потому что код выдавал бы NullPointerException в строке, bean2.setX(x); если bean2 бы было null. Тот факт, что код не запускается, является доказательством того, что Bean1 создается правильно (при условии, что вы видите сообщения журнала, поступающие из Bean1 init() метода).

5. Если я могу работать bean2.setX(x) в bean1 без каких-либо исключений, это означает, что Bean2 уже создан. Почему значение x не задано в Bean2? Кроме того, есть ли другой способ добиться этого?