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

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

Ответ

Да, Spring предоставляет несколько механизмов для управления жизненным циклом бина (от создания до уничтожения).

Основные способы:

  1. Аннотации JSR-250 (наиболее предпочтительный способ):

    @Component
    public class MyService {
        @PostConstruct
        public void init() {
            // Вызывается после инъекции всех зависимостей.
            // Идеально для инициализации ресурсов.
        }
        @PreDestroy
        public void cleanup() {
            // Вызывается перед уничтожением бина при закрытии контекста.
            // Идеально для освобождения ресурсов (закрытие соединений и т.д.).
        }
    }
  2. Интерфейсы Spring Lifecycle:

    @Component
    public class MyBean implements InitializingBean, DisposableBean {
        @Override
        public void afterPropertiesSet() { // Аналог @PostConstruct
            // Логика инициализации
        }
        @Override
        public void destroy() { // Аналог @PreDestroy
            // Логика очистки
        }
    }
  3. BeanPostProcessor (для продвинутого кастомизации): Позволяет вмешиваться в процесс инициализации любых бинов до/после их создания.

    @Component
    public class CustomBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            // Действия до вызова init-методов
            return bean;
        }
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            // Действия после вызова init-методов (например, создание прокси)
            return bean;
        }
    }
  4. XML-конфигурация (устаревший способ):

    <bean class="com.example.MyBean" init-method="customInit" destroy-method="customDestroy"/>

Стандартный порядок вызова методов инициализации:

  1. Конструктор.
  2. Инъекция зависимостей (через @Autowired/сеттеры).
  3. Метод postProcessBeforeInitialization всех BeanPostProcessor.
  4. Метод, помеченный @PostConstruct, или afterPropertiesSet().
  5. Метод postProcessAfterInitialization всех BeanPostProcessor.
  6. При завершении контекста: @PreDestroydestroy().