Каков жизненный цикл бина в Spring?

«Каков жизненный цикл бина в Spring?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Жизненный цикл бина (Spring Bean) в контейнере Spring управляется контейнером IoC и состоит из ключевых этапов:

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

  1. Создание экземпляра (Instantiation): Контейнер создает объект бина через конструктор (по умолчанию) или фабричный метод.
  2. Наполнение свойствами (Population of Properties): Spring внедряет зависимости (Dependency Injection) через поля, сеттеры или конструктор, используя @Autowired или XML-конфигурацию.
  3. Пост-обработка (Bean Post-Processing): Вызываются callback-методы и интерфейсы, позволяющие кастомизировать бин:
    • BeanPostProcessor: Глобальный механизм. Вызываются методы postProcessBeforeInitialization и postProcessAfterInitialization для всех бинов.
    • @PostConstruct (JSR-250): Аннотация для метода, который должен быть выполнен после инъекции зависимостей и перед тем, как бин будет готов к использованию.
    • InitializingBean: Интерфейс с методом afterPropertiesSet(). Аналогичен @PostConstruct, но является Spring-специфичным.
  4. Бин готов (Ready): Бин полностью инициализирован, находится в контексте (ApplicationContext) и может быть использован.
  5. Уничтожение (Destruction): Перед уничтожением контекста (например, при завершении работы приложения) вызываются методы очистки:
    • @PreDestroy (JSR-250): Аннотация для метода очистки.
    • DisposableBean: Интерфейс с методом destroy(). Spring-специфичная альтернатива @PreDestroy.

Практический пример:

import javax.annotation.*;
import org.springframework.stereotype.Component;

@Component
public class DatabaseService {

    @PostConstruct
    public void init() {
        // Выполняется после инъекции всех зависимостей
        System.out.println("Бин DatabaseService инициализирован. Подключение к БД...");
    }

    public void fetchData() {
        System.out.println("Получение данных...");
    }

    @PreDestroy
    public void cleanup() {
        // Выполняется перед уничтожением бина
        System.out.println("Закрытие соединений с БД. Очистка ресурсов.");
    }
}

Важно: Использование @PostConstruct и @PreDestroy (из пакета javax.annotation или jakarta.annotation) предпочтительнее, так как это стандарт JSR и не связывает код с Spring API.