Опишите жизненный цикл бина (Bean) в Spring-контейнере.

Ответ

Жизненный цикл бина в Spring управляется контейнером IoC и состоит из ключевых этапов, на которые можно влиять через callback-интерфейсы и аннотации.

Основные этапы:

  1. Создание экземпляра (Instantiation): Контейнер создает объект через конструктор (или фабричный метод).
  2. Наполнение свойствами (Population of properties): Внедрение зависимостей через @Autowired, сеттеры или поля.
  3. Сознание контейнера (Aware interfaces): Если бин реализует интерфейсы Aware, вызываются соответствующие методы (например, setBeanName).
  4. Пред-инициализация (BeanPostProcessor.pre): Вызываются методы postProcessBeforeInitialization() всех зарегистрированных BeanPostProcessor.
  5. Инициализация (Initialization):
    • Вызывается метод, помеченный аннотацией @PostConstruct.
    • Если бин реализует InitializingBean, вызывается afterPropertiesSet().
    • Выполняется кастомный метод init, указанный в @Bean(initMethod = "...") или XML.
  6. Пост-инициализация (BeanPostProcessor.post): Вызываются методы postProcessAfterInitialization() всех BeanPostProcessor (здесь работают AOP-прокси).
  7. Готов к использованию (Ready): Бин полностью инициализирован и находится в контексте.
  8. Уничтожение (Destruction): При закрытии контекста:
    • Вызывается метод, помеченный @PreDestroy.
    • Если бин реализует DisposableBean, вызывается destroy().
    • Выполняется кастомный метод destroy из @Bean(destroyMethod = "...").

Визуализация и пример:

@Component
public class LifecycleDemoBean implements BeanNameAware, InitializingBean, DisposableBean {
    @Override
    public void setBeanName(String name) {
        System.out.println("3. Aware: Bean name is " + name);
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("5.1 @PostConstruct");
    }

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

    @PreDestroy
    public void preDestroy() {
        System.out.println("8.1 @PreDestroy");
    }

    @Override
    public void destroy() {
        System.out.println("8.2 destroy()");
    }
}
// Порядок вывода:
// 3. Aware: Bean name is lifecycleDemoBean
// 5.1 @PostConstruct
// 5.2 afterPropertiesSet()
// ... (бин используется)
// 8.1 @PreDestroy
// 8.2 destroy()

Ответ 18+ 🔞

А, слушай, про жизненный цикл бина в Spring! Это ж классика, блядь. Ну, представь себе, как этот контейнер IoC, такой важный дядя, блядь, берёт и начинает из тебя, из обычного класса, делать управляемый бин. Весь процесс — это как будто тебя, сука, на конвейере собирают, только вместо болтов — аннотации хуярят.

Вот как эта ёбнутая матрёшка раскрывается:

  1. Рождение, блядь (Instantiation): Тут всё просто — контейнер берёт и вызывает конструктор. Хуяк — и объект есть. Как будто из ниоткуда материализовался, ёпта.
  2. Накачка свойствами (Population of properties): А вот тут начинается магия. Он смотрит: ага, тут @Autowired, тут сеттер, тут поле. И начинает, сука, впендюривать в тебя все зависимости, как заправский наркоман шприцы. «Держи, блядь, этот сервис! А вот этот репозиторий — в сраку получай!».
  3. Просветление (Aware interfaces): Если твой бин не лох и реализует всякие Aware интерфейсы, контейнер такой: «О, ты хочешь знать, как тебя зовут? Или где твой ApplicationContext? На, получай, мудак!». Вызывает setBeanName или setApplicationContext.
  4. Предстартовая подготовка (BeanPostProcessor.pre): А это, блядь, самые хитрые ребята — BeanPostProcessor-ы. Они как надзиратели на этапе. Каждый может подойти к почти готовому бину и сказать: «Постой-ка, дружок, я тут кое-что в тебя впиндюрить хочу перед главной инициализацией». Вызывается postProcessBeforeInitialization(). Типа последний шанс что-то подкрутить.
  5. Главная инициализация (Initialization): Вот тут уже твой бин начинает орать: «Я готов, ёба!». И события идут в строгом порядке, блядь, как в армии:
    • Первым делом — @PostConstruct. Аннотация-король, блядь. Метод, который пометил — тот и вызывается.
    • Потом, если бин — старый пердун и реализует InitializingBean, дергается afterPropertiesSet().
    • И в конце, как вишенка на торте — кастомный init-метод, который ты в @Bean указал или в XML прописал.
  6. Пост-обработка (BeanPostProcessor.post): А эти надзиратели-то ещё не закончили! После инициализации они снова налетают: «А теперь дай-ка я тебя проксирую для AOP!» или «А я тебе тут финальный штрих добавлю!». Это postProcessAfterInitialization(). Именно здесь часто рождаются те самые хитрые прокси, которые потом логирование или транзакции добавляют.
  7. Полная боевая готовность (Ready): Всё, пиздец. Бин созрел, как сыр в погребе. Он сидит в контексте, красивый, и ждёт, когда его @Autowired-нут куда надо.
  8. Закат, разрушение (Destruction): Контекст закрывается. Пришла пора на свалку истории. И тут тоже церемония, блядь, в обратном порядке:
    • Первым делуют @PreDestroy — последний шанс прибраться за собой.
    • Потом, если опять этот старый пердун DisposableBean, зовут его метод destroy().
    • И финальный аккорд — кастомный destroy-метод из аннотации или XML. Типа «прощай, и больше не возвращайся».

Чтоб не быть голословным, смотри, как это в коде выглядит, ёпта:

@Component
public class LifecycleDemoBean implements BeanNameAware, InitializingBean, DisposableBean {
    @Override
    public void setBeanName(String name) {
        System.out.println("3. Aware: Bean name is " + name); // Узнал своё имя, доволен как слон
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("5.1 @PostConstruct"); // Первый крик новорождённого бина
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("5.2 afterPropertiesSet()"); // Старая школа рулит
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("8.1 @PreDestroy"); // Последние слова перед гибелью
    }

    @Override
    public void destroy() {
        System.out.println("8.2 destroy()"); // Финальный вздох
    }
}
// И когда это всё запустится, в консоли будет такая песня:
// 3. Aware: Bean name is lifecycleDemoBean
// 5.1 @PostConstruct
// 5.2 afterPropertiesSet()
// ... (тут бин пашет, как папа Карло)
// 8.1 @PreDestroy
// 8.2 destroy()

Вот и вся магия, блядь. Сначала тебя собирают по кускам, потом накачивают зависимостями, дают имя, дают последние инструкции, а потом, когда контекст прикроют — ещё и за собой прибраться заставят. Красота, ёперный театр!