Жизненный цикл бина в Spring проходит через несколько ключевых этапов: создание, внедрение зависимостей, инициализацию, обработку пост-процессорами и уничтожение.
Понимание этого процесса помогает правильно управлять зависимостями, использовать AOP, кэширование и корректно работать с ресурсами.
В этой статье разберем каждый этап на понятных примерах:
Этап 1. Создание бина (Instantiation)
Spring создает объект бина с помощью конструктора, но пока не внедряет в него зависимости.
Пример из жизни: Вы купили кофеварку, но еще не подключили ее к сети и не залили воду.
Этап 2. Внедрение зависимостей (Dependency Injection)
Spring автоматически добавляет в бин все его зависимости.
Аналогия: Вы подключили кофеварку к сети и залили воду.
Способы внедрения зависимостей:
-
Через конструктор – рекомендуется для обязательных зависимостей, в комбинации с модификатором final обеспечивает неизменяемость объекта.
-
Через поле — @Autowired можно ставить на поле, и Spring внедрит зависимость. Однако этот способ не рекомендуется, так как он усложняет тестирование и делает зависимость менее явной.
-
Через сеттеры – используется, если зависимость может изменяться после создания бина.
-
Через аннотации @Value, @Qualifier и др. – применяется для внедрения простых значений и указания конкретного бина при наличии нескольких кандидатов.
Этап 3. Aware-интерфейсы
Если бин реализует BeanNameAware, BeanFactoryAware, ApplicationContextAware, Spring передает ему информацию о контексте.
Пример из жизни: Кофеварка проверяет напряжение в сети перед включением.
-
BeanNameAware — получает имя бина
-
BeanFactoryAware — доступ к BeanFactory
-
ApplicationContextAware — доступ ко всему контексту Spring
Используйте их с осторожностью, так как это привязывает код к Spring API и усложняет тестирование.
Этап 4. BeanPostProcessor до инициализации
Spring вызывает postProcessBeforeInitialization у всех BeanPostProcessor.
Примеры использования:
-
Валидация бинов – проверка корректности данных перед их использованием.
-
Изменение свойств – настройка конфигурации бина в зависимости от профиля приложения (@Profile).
-
Логирование – запись информации о бине перед его инициализацией.
Этап 5. Инициализация (init)
Spring выполняет методы:
-
@PostConstruct
-
InitializingBean#afterPropertiesSet()
-
Метод, указанный в @Bean(initMethod = «init»)
Пример: Кофеварка прогревает воду перед приготовлением кофе.
Здесь можно проверять настройки бина и подключаться к ресурсам (например, БД).
Этап 6. BeanPostProcessor после инициализации
Spring вызывает postProcessAfterInitialization у BeanPostProcessor.
Где применяется:
-
Проксирование бинов – создание AOP-прокси для аннотаций @Transactional, @Async и подобных.
-
Кэширование – автоматическое добавление механизма кэширования для методов.
-
Изменение бинов – динамическое добавление новых методов или обертывание логикой безопасности.
При использовании проксирования бин может подменяться Spring-оберткой (важно при instanceof).
Этап 7. Уничтожение бина (destroy)
Spring вызывает:
-
@PreDestroy
-
DisposableBean#destroy()
-
Метод, указанный в @Bean(destroyMethod = «cleanup»)
Пример: Вы выключаете кофеварку, сливаете воду, чистите фильтр и убираете ее.
Для prototype-бинов этот этап не вызывается — их уничтожение нужно обрабатывать вручную.
Пример кода
Код
// Главный бин с логами всех этапов @Component class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean { private String beanName; private ApplicationContext context; public MyBean() { System.out.println("1. Конструктор MyBean вызван (Instantiation)"); } @Autowired public void setDependency(MyDependency dependency) { System.out.println("2. Зависимость MyDependency внедрена (DI)"); } @Override public void setBeanName(String name) { this.beanName = name; System.out.println("3. BeanNameAware: Имя бина - " + name); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; System.out.println("3. ApplicationContextAware: Контекст передан"); } @PostConstruct public void postConstruct() { System.out.println("5. @PostConstruct: Бин проинициализирован"); } @Override public void afterPropertiesSet() { System.out.println("5. InitializingBean: Бин завершил инициализацию"); } @PreDestroy public void preDestroy() { System.out.println("7. @PreDestroy: Перед уничтожением бина"); } @Override public void destroy() { System.out.println("7. DisposableBean: Бин уничтожен"); } } // Дополнительный бин для DI @Component class MyDependency { public MyDependency() { System.out.println("1. Конструктор MyDependency вызван (Instantiation)"); } } // BeanPostProcessor для логирования этапов postProcessBeforeInitialization и postProcessAfterInitialization @Component class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { if (bean instanceof MyBean) { System.out.println("4. BeanPostProcessor: Before Init - " + beanName); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof MyBean) { System.out.println("6. BeanPostProcessor: After Init - " + beanName); } return bean; } } @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
Вывод в консоль
1. Конструктор MyDependency вызван (Instantiation) 1. Конструктор MyBean вызван (Instantiation) 2. Зависимость MyDependency внедрена (DI) 3. BeanNameAware: Имя бина - myBean 3. ApplicationContextAware: Контекст передан 4. BeanPostProcessor: Before Init - myBean 5. @PostConstruct: Бин проинициализирован 5. InitializingBean: Бин завершил инициализацию 6. BeanPostProcessor: After Init - myBean >>> Контекст запущен >>> Закрытие контекста 7. @PreDestroy: Перед уничтожением бина 7. DisposableBean: Бин уничтожен
Выводы:
-
BeanPostProcessor используется для оберток и проксирования.
-
Aware-интерфейсы дают доступ к Spring-контексту, но не злоупотребляйте ими.
-
Правильное использование @PostConstruct и @PreDestroy упрощает управление ресурсами.
ссылка на оригинал статьи https://habr.com/ru/articles/893614/
Добавить комментарий