Атрибут Spring @PostConstruct vs. init


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 (квасоля) від будь-яких весняних специфічних класів / анотацій. Отже, якщо ви будуєте бібліотеку, яка не повинна залежати від весняної інфраструктури тоді метод init був кращим. Під час створення u можна вказати метод, який потрібно називати методом ініціалізації.

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

Але я повинен визнати, що додавання цих речей підвищує читабельність коду. Отже, є плюси і мінуси обох підходів.


23
Якщо боб використовує більш ніж один із цих методів і покладається на порядок ініціалізації, це буде жахливо складним і неможливим.
Дональні стипендіати

2
@Donal Цілком правда. Просто надав інформацію про те, як це працює.
Aravind A

1
Існує важлива відмінність: Ви повинні спеціально для конфігурації Spring процесу анотацій зробити @PostConstruct роботи: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, але вам потрібно це знати, якщо ви плануєте складати сертифікаційні іспити;)
С.Клечковський

@DonalFellows - Чи можете ви, будь ласка, розробити свою відповідь? Я маю на увазі труднощі, з якими стикається, якщо боб покладається на порядок ініціалізації. Насправді я хочу знати, хто з них кращий. PostConstruct або Bean (initMethod = "init"), щоб зробити деякі ініціалізаційні речі з файлу, перш ніж він подаватиме запити?
Аяскант

19

Немає реальної різниці. Це залежить від того, як ви віддаєте перевагу налаштування системи, і це питання особистого вибору. Сам я вважаю за краще використовувати @PostConstructанотації для власного коду (оскільки квасоля правильно налаштована лише після виклику методу), і я використовую, init-methodколи інстанціювати боби з бібліотек, що не знають Spring (звичайно, не можу застосовувати анотації там, звичайно!) але я цілком можу зрозуміти людей, які хочуть це зробити так чи інакше.


4

@postconstruct не є частиною весни. Він є частиною пакету javax. Обидва однакові. використовуючи метод init, нам потрібно додати файл xml. Якщо ви використовуєте @postconstruct, додавання в xml не потрібно. Перегляньте статтю нижче.

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


3

Як ви бачите на наведеній нижче схемі зворотного зворотного виклику Bean Creation .

Зворотний виклик життєвого циклу створення квасолі

Цей 3 крок відбувається під час зворотного виклику життєвого циклу створення Bean:

  1. Згадується, що @PostConstructбуде називатися.
  2. Якщо InitializingBeanбуде реалізовано, тоді afterPropertiesSet()буде викликано.
  3. Якщо визначення bean містить init-methodабо @Bean(initmethod="..")тоді він викликає метод init.

Ця діаграма зібрана з програми Pro Spring 5: Поглиблене керівництво до рамки весни та її інструментів


3

Там може бути різниця між @PostConstructі init-methodтому , що @PostConstructобробляється в postProcessAfterInitializationфазі ініціалізації бобу ( AbstractAutowireCapableBeanFactory.initializeBean()метод) з допомогою CommonAnnotationBeanPostProcessor, в той час як initметод викликається після завершення postProcessBeforeInitializationфази (і, з цього питання, до початку postProcessAfterInitializationфази).
EDIT : Отже, послідовність: 1) postProcessBeforeInitializationфаза, 2) initвикликається метод, 3) postProcessAfterInitializationфаза, яка викликає @PostConstructметод

(Як бічна примітка, заява з прийнятої відповіді

@PostConstruct, метод init - це BeanPostProcessors

не зовсім коректно: @PostConstructобробляється методом a BeanPostProcessor, initметод не є.)

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

На закінчення, прийнята відповідь і подібне є правильним ... у 99% випадків, і ця посада лише для того, щоб віддати належне поняттю "чорт у деталях"


Привіт! Це заплутано, якщо PostConstruct працює перед init-методом, як це обробляється postProcessAfterInitialization, якщо метод init працює після postProcessBeforeInitialization та перед postProcessAfterInitialization ???
Maxrunner

@Maxrunner, вибачте за плутанину і дякую за те, що повідомили! Насправді я ніколи не хотів сказати, що PostConstruct працює перед init-методом. У будь-якому випадку я оновив свою відповідь деякими уточненнями
igor.zh

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 in afterPropertiesSet: [Magic]
...

Реєстрація бобів для експозиції JMX під час запуску.
Початок DemoApplication за 0,561 секунди (JVM працює на 1,011)
Закриття org.springframework.context .. Видалення JMX-бобів під час відключення

...
MyComponent в preDestroy: [Магія]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.