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

«Опишите жизненный цикл бина (Bean) в Spring-контейнере.» — вопрос из категории Spring, который задают на 29% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Жизненный цикл бина в 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()