Каков жизненный цикл объекта (бина), управляемого Spring?

Ответ

Жизненный цикл объекта (бина), управляемого Spring IoC-контейнером, включает этапы от инстанциирования до уничтожения, с точками расширения для кастомной логики. Это более общая формулировка, аналогичная жизненному циклу бина.

Полная последовательность с точками расширения:

  1. Инстанциирование бина — создание экземпляра класса.
  2. Заполнение свойств (Dependency Injection) — внедрение значений и ссылок на другие бины.
  3. События BeanNameAware, BeanFactoryAware и др. — если бин реализует соответствующие интерфейсы.
  4. BeanPostProcessor.preProcessBeforeInitialization() — вызов методов всех зарегистрированных BeanPostProcessor-ов.
  5. Инициализация:
    • Методы @PostConstruct.
    • InitializingBean.afterPropertiesSet().
    • Кастомный метод init.
  6. BeanPostProcessor.postProcessAfterInitialization() — финальная пост-обработка бина.
  7. Бин готов к использованию в контексте.
  8. Уничтожение контекстаУничтожение бина:
    • Методы @PreDestroy.
    • DisposableBean.destroy().
    • Кастомный метод destroy.

Пример, демонстрирующий несколько этапов:

@Component
public class ExampleBean implements BeanNameAware, InitializingBean, DisposableBean {
    private String name;

    @Override
    public void setBeanName(String name) {
        this.name = name; // BeanNameAware callback
        System.out.println("Bean name set: " + name);
    }

    @PostConstruct
    public void customInit() {
        System.out.println("@PostConstruct method called");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("InitializingBean.afterPropertiesSet() called");
    }

    @Override
    public void destroy() {
        System.out.println("DisposableBean.destroy() called");
    }
}

BeanPostProcessor — это мощный механизм для модификации бинов на уровне контейнера (например, для проксирования, как в Spring AOP).

Ответ 18+ 🔞

Давай разберём эту всю хуйню про жизненный цикл бина в Спринге, а то смотришь на список этапов — и волосы дыбом, блядь. Это ж как в плохом анекдоте: «родился, крестился, женился, помер». Только тут этапов дохуя больше, и половину из них можно пропустить, если не хочешь заморачиваться.

Представь себе, что Спринг — это такой суровый дядя-начальник на заводе. А твой бин — это новый станок, который привезли в цех.

Вот как это происходит, по шагам, с матами и без:

  1. Инстанциирование. Дядя Спринг берёт чертёж (твой класс) и говорит: «Так, хули тут думать — твори!». И из кучи металлолома (из памяти, блядь) собирает голый, ни к чему не прикрученный станок. Просто железка, которая даже не знает, как её зовут.
  2. Заполнение свойств (Dependency Injection). А вот тут начинается самое интересное. Дядя подходит и начинает в этот станок вкручивать всякие пиздатые штуки: «Это тебе маслёнка (другой бин), это тебе рычаг (какое-то значение из пропертей), а это, сука, предохранитель (ещё один бин)». Станок начинает обрастать деталями, но всё ещё молчит, как партизан.
  3. Осознание себя (Aware-интерфейсы). Тут станок может охуеть и спросить: «А как, блядь, меня зовут-то?» (BeanNameAware). Или: «А кто мой начальник-то?» (BeanFactoryAware). Если он реализует эти интерфейсы — дядя Спринг ему шепнёт на ушко нужную инфу. Не реализует — и хуй с ним, живёт в неведении.
  4. Предварительный допрос (BeanPostProcessor.preProcessBeforeInitialization). А перед тем, как станок запустить, по конвейеру идёт особый надзиратель — BeanPostProcessor. Он может подойти к каждому свежесобранному станку, потрогать его, хмыкнуть и сказать: «Ну-ка, покажься, что ты за хуйня такая?». Может даже что-то мелкое подкрутить. Это точка для всякой низкоуровневой магии, типа обёрток для АОП.
  5. ИНИЦИАЛИЗАЦИЯ. Торжественный запуск. Вот тут станок, наконец, включают. И делают это аж тремя разными способами, можно хоть одним, можно всеми — как хочешь, ёпта:
    • @PostConstruct — Самый модный и современный способ. Как будто на станке кнопку «Старт» нажали.
    • InitializingBean.afterPropertiesSet() — Старый, дедовский способ. Станок сам кричит: «Я готов, ёбта! Все детали на месте, давайте работать!».
    • Кастомный init-метод — Способ для тех, кто любит всё контролировать. Сам в конфиге сказал, какой метод вызывать для запуска.
  6. Финальный осмотр (BeanPostProcessor.postProcessAfterInitialization). Надзиратель (BeanPostProcessor) снова идёт по цеху, но теперь смотрит на уже работающие станки. Тут происходит самое пиздатое — например, этот надзиратель может подсунуть станку его злого двойника-прокси, который будет следить, чтобы станок не делал лишних движений (это про АОП, если чё).
  7. Бин готов. Всё, пипец. Станок гудит, детали вращаются, он делает свою работу — отдаёт методы, внедряется в другие бины, короче, живёт полной жизнью.
  8. РАЗБОРКА ПОЛЁТОВ. Уничтожение. Рабочий день кончился, дядя Спринг (контейнер) закрывает цех. Он подходит к каждому станку и говорит: «Всё, мудила, заканчивай!». И выключает его, тоже тремя путями:
    • @PreDestroy — Вежливо нажимает кнопку «Стоп».
    • DisposableBean.destroy() — Станок сам орет: «Я щас самовыпилюсь!».
    • Кастомный destroy-метод — Как договаривались в конфиге.

А вот пример кода, где этот самый станок пытается понять, кто он такой, и орет при рождении и смерти:

@Component
public class ExampleBean implements BeanNameAware, InitializingBean, DisposableBean {
    private String name;

    @Override
    public void setBeanName(String name) {
        this.name = name; // Тут бин узнаёт своё кодовое имя от контейнера
        System.out.println("Бля, меня назвали: " + name);
    }

    @PostConstruct
    public void customInit() {
        System.out.println("Кто-то нажал @PostConstruct! Я оживаю!");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("Йоу! Все зависимости заебашены! InitializingBean рулит!");
    }

    @Override
    public void destroy() {
        System.out.println("Всё, пиздец мне. DisposableBean вызывает диспоуз...");
    }
}

А BeanPostProcessor — это вообще отдельная песня. Это как спецназ в контейнере. Он может подсунуть любому бину прокси, подменить ему методы, навесить хуйню — в общем, творить, что захочет, пока бины идут по конвейеру. Без него не было бы половины крутых фич Спринга.