Spring @PostConstruct против атрибута init-method

103

Есть ли разница между использованием @PostConstructаннотации и объявлением того же метода, что и init-methodв конфигурации Spring XML?

Ян Зыка
источник

Ответы:

153

Нет, практически я не думаю, что есть какая-то разница, но есть приоритеты в том, как они работают. @PostConstruct, init-methodявляются BeanPostProcessors.

  1. @PostConstruct- это аннотация JSR-250, а init-methodв Spring - метод инициализации.
  2. Если у вас есть @PostConstructметод, он будет вызываться перед вызовом методов инициализации.
  3. Если ваш компонент реализует InitializingBean и переопределяет afterPropertiesSet, сначала @PostConstructвызывается, затем, afterPropertiesSetа затем init-method.

Для получения дополнительной информации вы можете проверить справочную документацию Spring .

До спецификаций JSR 250 использование init-метода в xml было предпочтительным способом, поскольку он отделяет классы Java (beans) от любых классов / аннотаций, специфичных для Spring. Так что, если вы создаете библиотеку, которая не должна зависеть от компонентов инфраструктуры Spring тогда предпочтительным было использование init-метода. Во время создания метода u может указать метод, который должен быть вызван как метод инициализации.

Теперь, с введением спецификаций JSR 250 в Java EE и поддержкой Spring этих аннотаций, зависимость от фреймворка Spring в определенной степени уменьшилась.

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

Аравинд А
источник
23
Если bean-компонент использует более одного из этих методов и зависит от порядка инициализации, он будет ужасно сложным и неподдерживаемым.
Donal Fellows
2
@Donal Совершенно верно. Просто давал информацию о том, как это работает.
Aravind A
1
Есть важное различие: вам нужно специально настроить Spring для обработки аннотаций, чтобы @PostConstruct работал: stackoverflow.com/q/3434377/134898
Хуан Калеро
@DonalFellows, но вам нужно это знать, если вы планируете сдавать сертификационные экзамены;)
С.Клечковский
@DonalFellows - Не могли бы вы уточнить свой ответ? Я имею в виду трудности, возникающие, если bean-компонент зависит от порядка инициализации. На самом деле я хочу знать, какой из них лучше. PostConstruct или Bean (initMethod = "init"), чтобы выполнить некоторую инициализацию из bean-компонента, прежде чем он обслужит какие-либо запросы?
Ayaskant
19

Нет никакой реальной разницы. Все зависит от того, как вы предпочитаете настраивать свою систему, и это вопрос личного выбора. Лично я предпочитаю использовать @PostConstructаннотации для своего собственного кода (поскольку bean-компонент правильно настроен только после вызова метода), и я использую init-methodпри создании экземпляров bean-компонентов из библиотек, не поддерживающих Spring (конечно, нельзя применять там аннотации!) но я могу полностью понять людей, которые так или иначе хотят все это делать.

Donal Fellows
источник
4

@postconstruct не является частью весны. Это часть пакета javax. Оба одинаковые. с помощью init-метода нам нужно добавить в xml файл. Если вы используете @postconstruct, добавление в xml не требуется. Ознакомьтесь со статьей ниже.

http://answersz.com/spring-postconstruct-and-predestroy/

Амрут М Радж
источник
3

Как вы можете видеть на приведенной ниже диаграмме обратного вызова жизненного цикла создания компонента .

Обратный вызов жизненного цикла создания компонента

Эти 3 шага выполняются в обратном вызове жизненного цикла создания компонента:

  1. Упоминается, что @PostConstructбудет называться.
  2. Если InitializingBeanреализовано, то afterPropertiesSet()будет называться.
  3. Если определение bean-компонента содержит init-methodили @Bean(initmethod="..")вызывает метод init.

Эта диаграмма взята из Pro Spring 5: подробное руководство по Spring Framework и ее инструментам.

yashjain12yj
источник
3

Там может быть разница между @PostConstructи init-methodпотому , что @PostConstructобрабатывается в postProcessAfterInitializationфазе инициализации боба ( AbstractAutowireCapableBeanFactory.initializeBean()метод) с помощью CommonAnnotationBeanPostProcessor, в то время как initметод вызывается после завершения postProcessBeforeInitializationфазы (и, по этому вопросу, до начала postProcessAfterInitializationфазы).
РЕДАКТИРОВАТЬ : Итак, последовательность: 1) postProcessBeforeInitializationфаза, 2) вызывается метод init, 3) postProcessAfterInitializationфаза, которая вызывает @PostConstructметод

(В качестве примечания, заявление из принятого ответа

@PostConstruct, метод инициализации - это BeanPostProcessors

не совсем правильно: @PostConstructобрабатывается a BeanPostProcessor, initметод - нет.)

Там будет разница , если некоторые (возможно под заказ) BeanPostProcessor, который выполнен с ( Ordered.getOrder()) , который будет выполняться после того, как CommonAnnotationBeanPostProcessor, делает что - то серьезное в его postProcessBeforeInitializationметоде.
Нет никакой разницы с конфигурацией Spring по умолчанию, BeanPostProcessorsпотому что все, BeanPostProcessorsкоторые настроены для выполнения после CommonAnnotationBeanPostProcessor, ничего не делают в postProcessBeforeInitializationметоде.

В заключение, принятый ответ и подобные ему верны ... в 99% случаев, и этот пост - просто дань уважения концепции "дьявол кроется в деталях"

игорь.ж
источник
Здравствуй! Это сбивает с толку, если PostConstruct запускается до метода инициализации, как это обрабатывается postProcessAfterInitialization, если метод инициализации запускается после postProcessBeforeInitialization и до postProcessAfterInitialization ???
Maxrunner
@Maxrunner, извините за недоразумение и большое спасибо за сообщение! На самом деле, я никогда не имел в виду, что PostConstruct запускается до init-метода. Во всяком случае, я обновил свой ответ некоторыми уточнениями
igor.zh 05
2

Полный код здесь: https://github.com/wkaczurba/so8519187 ( spring-boot )

Использование аннотаций:

@Slf4j
@Component
public class MyComponent implements InitializingBean {

    @Value("${mycomponent.value:Magic}")
    public String value;

    public MyComponent() {
        log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null
    }

    @PostConstruct
    public void postConstruct() {
        log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
    }

    @Override // init-method; overrides InitializingBean.afterPropertiesSet()
    public void afterPropertiesSet() {
        log.info("MyComponent in afterPropertiesSet: [{}]", value);  // (2) displays: Magic
    }   

    @PreDestroy
    public void preDestroy() {
        log.info("MyComponent in preDestroy: [{}]", value); // (3) displays: Magic
    }
}

Получает нас:

Обновление org.springframework.context ...

MyComponent в конструкторе: [null]
MyComponent в postConstruct: [Magic]
MyComponent в afterPropertiesSet: [Magic]
...

Регистрация bean-компонентов для
отображения JMX при запуске Запущено DemoApplication через 0,561 секунды (JVM работает для 1.011)
Закрытие org.springframework.context .. . Отмена регистрации JMX-компонентов при завершении работы

...
MyComponent в preDestroy: [Magic]

Витольд Качурба
источник