Что такое жизненный цикл Bean?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Жизненный цикл Bean в Spring Framework
Bean Lifecycle — это набор этапов, через которые проходит объект (bean) от создания до удаления в контейнере Spring. Понимание этого процесса критично для правильного использования Spring Framework.
Основные этапы жизненного цикла
1. Instantiation (создание объекта)
Spring создаёт экземпляр класса через конструктор (с параметрами или без).
@Component
public class MyBean {
// Spring вызывает конструктор
public MyBean() {
System.out.println("1. Instantiation - Bean создан");
}
}
2. Populate Properties (установка свойств)
Spring устанавливает значения полей через setter-методы или поля с аннотацией @Autowired.
@Component
public class MyBean {
@Autowired
private SomeService service; // Будет инжектирован здесь
@Value("${app.name}")
private String appName; // Будет установлено здесь
}
3. setBeanName (установка имени bean)
Если bean имплементирует BeanNameAware, Spring передаёт имя bean.
@Component
public class MyBean implements BeanNameAware {
@Override
public void setBeanName(String name) {
System.out.println("3. BeanNameAware.setBeanName: " + name);
}
}
4. setBeanFactory (установка factory)
Если bean имплементирует BeanFactoryAware.
@Component
public class MyBean implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory)
throws BeansException {
System.out.println("4. BeanFactoryAware.setBeanFactory вызван");
}
}
5. setApplicationContext (установка context)
Если bean имплементирует ApplicationContextAware.
@Component
public class MyBean implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
System.out.println("5. ApplicationContextAware.setApplicationContext вызван");
}
}
6. BeanPostProcessor.postProcessBeforeInitialization
Вызывается после инъекции зависимостей, но ДО инициализации bean.
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof MyBean) {
System.out.println("6. postProcessBeforeInitialization для " + beanName);
}
return bean;
}
}
7. @PostConstruct / afterPropertiesSet
Вызывается ПОСЛЕ инъекции всех зависимостей. Это идеальное место для инициализации.
@Component
public class MyBean implements InitializingBean {
private List<String> data;
// Вариант 1: с помощью @PostConstruct
@PostConstruct
public void init() {
System.out.println("7a. @PostConstruct init вызван");
data = new ArrayList<>();
data.add("initialized");
}
// Вариант 2: с помощью InitializingBean
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("7b. InitializingBean.afterPropertiesSet вызван");
}
// Вариант 3: initMethod в @Bean
public void customInit() {
System.out.println("7c. Кастомный initMethod");
}
}
8. BeanPostProcessor.postProcessAfterInitialization
Вызывается ПОСЛЕ инициализации bean.
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof MyBean) {
System.out.println("8. postProcessAfterInitialization для " + beanName);
}
return bean;
}
}
9. Ready to Use
Bean полностью инициализирован и готов к использованию.
@Component
public class MyBean {
public void doSomething() {
System.out.println("9. Bean готов к использованию");
}
}
10. @PreDestroy / destroy
Вызывается ДО уничтожения bean (при закрытии context). Используется для очистки ресурсов.
@Component
public class MyBean implements DisposableBean {
private Connection dbConnection;
@PostConstruct
public void init() {
// Открываем соединение
dbConnection = createConnection();
}
// Вариант 1: @PreDestroy
@PreDestroy
public void cleanup() {
System.out.println("10a. @PreDestroy cleanup вызван");
if (dbConnection != null) {
dbConnection.close();
}
}
// Вариант 2: DisposableBean
@Override
public void destroy() throws Exception {
System.out.println("10b. DisposableBean.destroy вызван");
}
// Вариант 3: destroyMethod в @Bean
public void customDestroy() {
System.out.println("10c. Кастомный destroyMethod");
}
}
Полный пример с демонстрацией
@Component
public class FullLifecycleBean implements
BeanNameAware,
BeanFactoryAware,
ApplicationContextAware,
InitializingBean,
DisposableBean {
private String name;
public FullLifecycleBean() {
System.out.println("1. Instantiation");
}
@Autowired
public void setName(String appName) {
this.name = appName;
System.out.println("2. Property injected: " + appName);
}
@Override
public void setBeanName(String name) {
System.out.println("3. setBeanName: " + name);
}
@Override
public void setBeanFactory(BeanFactory factory) {
System.out.println("4. setBeanFactory");
}
@Override
public void setApplicationContext(ApplicationContext context) {
System.out.println("5. setApplicationContext");
}
@PostConstruct
public void postConstruct() {
System.out.println("7. @PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("7b. afterPropertiesSet");
}
@PreDestroy
public void preDestroy() {
System.out.println("10. @PreDestroy");
}
@Override
public void destroy() {
System.out.println("10b. destroy");
}
}
Вывод при запуске:
1. Instantiation
2. Property injected: myapp
3. setBeanName: fullLifecycleBean
4. setBeanFactory
5. setApplicationContext
7. @PostConstruct
7b. afterPropertiesSet
[Bean готов к использованию]
10. @PreDestroy
10b. destroy
Конфигурирование через @Bean
@Configuration
public class BeanConfig {
@Bean(initMethod = "init", destroyMethod = "cleanup")
public MyService myService() {
return new MyService();
}
}
public class MyService {
public void init() {
System.out.println("Инициализация через initMethod");
}
public void cleanup() {
System.out.println("Очистка через destroyMethod");
}
}
Scope и жизненный цикл
Длительность жизни bean зависит от scope:
// Singleton (по умолчанию)
@Component // или @Bean
public class SingletonBean {}
// Один экземпляр на весь контекст
// Prototype
@Component
@Scope("prototype")
public class PrototypeBean {}
// Новый экземпляр каждый раз
// Request scope (web)
@Component
@Scope("request")
public class RequestBean {}
// Новый экземпляр на каждый HTTP request
Лучшие практики
- Используй @PostConstruct вместо конструктора — для инициализации логики
- Используй @PreDestroy — для освобождения ресурсов
- Избегай сложной логики в конструкторе — конструктор должен быть простым
- Будь осторожен с BeanPostProcessor — может замедлить инициализацию
- Помни о порядке — @PostConstruct вызывается после инъекции зависимостей
Заключение
Жизненный цикл Bean — это сложная, но мощная система, позволяющая Spring фреймворку полностью управлять объектами. Глубокое понимание этапов критично для написания правильного Spring кода и избежания проблем с инициализацией и очисткой ресурсов.