← Назад к вопросам
Как устроен жизненный цикл Spring приложений?
2.0 Middle🔥 201 комментариев
#Spring Framework
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Жизненный цикл Spring приложений
Жизненный цикл Spring приложения — это последовательность этапов инициализации и выключения контейнера Bean, управления зависимостями и выполнения хуков на каждом этапе.
Фазы жизненного цикла
1. Инициализация (Bootstrapping)
Создание контекста (ApplicationContext):
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml"
);
// или с Java конфигом
ApplicationContext context = new AnnotationConfigApplicationContext(
AppConfig.class
);
Что происходит:
- Spring читает конфигурацию (XML, Java config, properties)
- Создаёт bean definitions для каждого bean-а
- Инициализирует сам контейнер
2. Bean Instantiation (Создание экземпляров)
Фазы для каждого bean-а:
а) Создание объекта:
- Spring использует рефлексию или конструктор
- Если задан factory-method, то используется он
б) Dependency Injection:
@Component
public class UserService {
private final UserRepository repository;
// Constructor injection (рекомендуется)
public UserService(UserRepository repository) {
this.repository = repository;
}
}
в) Setter injection:
@Component
public class OrderService {
private PaymentService paymentService;
@Autowired
public void setPaymentService(PaymentService service) {
this.paymentService = service;
}
}
3. Bean Post-Processing
BeanPostProcessor интерфейс:
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("Before init: " + beanName);
return bean; // можно вернуть другой bean
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("After init: " + beanName);
return bean;
}
}
Примеры BeanPostProcessor:
@Autowiredобработчик@ConfigurationPropertiesобработчик- AOP proxies
4. Инициализация Bean-а
Способ 1: @PostConstruct аннотация (рекомендуется):
@Component
public class DatabaseConnection {
@PostConstruct
public void init() {
System.out.println("Инициализация подключения к БД");
// подключение, загрузка данных, и т.д.
}
}
Способ 2: InitializingBean интерфейс:
@Component
public class OldStyleService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Bean инициализирован");
}
}
Способ 3: init-method в конфиге:
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public MyService myService() {
return new MyService();
}
}
5. Использование Bean-а
@Service
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService; // готов к использованию
}
public void getUser(Long id) {
User user = userService.findById(id);
}
}
6. Деструкция (Shutdown)
При выключении приложения:
BeanPostProcessor для деструкции:
@Component
public class ShutdownBeanPostProcessor implements BeanPostProcessor {
// Вызывается перед разрушением
}
Способ 1: @PreDestroy аннотация (рекомендуется):
@Component
public class DatabaseConnection {
@PreDestroy
public void destroy() {
System.out.println("Закрытие подключения к БД");
// закрытие ресурсов
}
}
Способ 2: DisposableBean интерфейс:
@Component
public class ResourceManager implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("Освобождение ресурсов");
}
}
Способ 3: destroyMethod в конфиге:
@Configuration
public class AppConfig {
@Bean(destroyMethod = "close")
public DataSource dataSource() {
return new DataSource();
}
}
Полный цикл Bean-а
1. BeanNameAware.setBeanName()
2. BeanClassLoaderAware.setBeanClassLoader()
3. BeanFactoryAware.setBeanFactory()
4. ApplicationContextAware.setApplicationContext()
5. BeanPostProcessor.postProcessBeforeInitialization()
6. @PostConstruct / InitializingBean.afterPropertiesSet()
7. BeanPostProcessor.postProcessAfterInitialization()
[Bean готов к использованию]
8. @PreDestroy / DisposableBean.destroy()
Практический пример
@Component
public class CompleteLifecycleBean
implements InitializingBean, DisposableBean,
ApplicationContextAware, BeanNameAware {
private String beanName;
private ApplicationContext context;
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("1. setBeanName: " + name);
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
this.context = ctx;
System.out.println("2. setApplicationContext");
}
@PostConstruct
public void postConstruct() {
System.out.println("3. @PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("4. afterPropertiesSet");
}
public void doSomething() {
System.out.println("5. Bean используется");
}
@PreDestroy
public void preDestroy() {
System.out.println("6. @PreDestroy");
}
@Override
public void destroy() {
System.out.println("7. destroy()");
}
}
Рекомендации
- Используй @PostConstruct/@PreDestroy — это стандарт Jakarta EE
- Избегай InitializingBean/DisposableBean — старый подход
- Не делай тяжёлую логику в конструкторе — это усложняет тестирование
- Используй constructor injection вместо field injection