JavaRush /Курси /Модуль 5. Spring /Управління життєвим циклом Spring Beans

Управління життєвим циклом Spring Beans

Модуль 5. Spring
Рівень 2 , Лекція 3
Відкрита

1. Пірнаємо в життєвий цикл Spring Beans

Основні етапи життєвого циклу Spring Bean:

  1. Створення (Initialization): IoC-контейнер створює об'єкт (bean) і виконує впровадження всіх залежностей.
  2. Ініціалізація (Post Initialization): виконуються додаткові операції, такі як налаштування і запуск потрібних процесів.
  3. Знищення (Destruction): перед завершенням роботи контейнера bean може завершити свої задачі, звільнити ресурси і виконати очистку.

Давайте розберемося, як Spring керує цими етапами і які інструменти він надає для їх налаштування.


2. Як IoC-контейнер керує життєвим циклом?

Spring IoC-контейнер відповідає за:

  • Створення об'єктів за конфігурацією або анотаціями
  • Додавання залежностей у bean
  • Запуск методів ініціалізації
  • Виклик методів завершення роботи, коли bean стає непотрібним

У реальному застосунку це відбувається так:

  1. Spring створює Bean
  2. Spring додає залежності через DI (@Autowired, @Bean, @Component)
  3. Spring запускає методи з анотацією @PostConstruct після створення об'єкта
  4. При закритті додатку Spring викликає методи з анотацією @PreDestroy, щоб коректно завершити роботу об'єкта

3. Використання анотацій для роботи з життєвим циклом

Spring надає зручні анотації для управління життєвим циклом бина: @PostConstruct і @PreDestroy. А тепер детальніше.

@PostConstruct: метод ініціалізації

Ця анотація визначає метод, який викликається після завершення створення об'єкта і впровадження залежностей. Вона ідеально підходить для додаткового налаштування об'єкта перед його використанням.

Приклад:


import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class CoffeeMaker {

    @PostConstruct
    public void heatUp() {
        System.out.println("Кавоварка нагрівається...");
    }
}

Коли Spring створює бин CoffeeMaker, він автоматично викличе метод heatUp після того, як усі залежності будуть налаштовані.


@PreDestroy: метод завершення роботи

Ця анотація вказує на метод, який буде викликаний перед знищенням об'єкта. Це корисно для звільнення ресурсів або виконання підсумкових задач.

Приклад:


import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

@Component
public class CoffeeMaker {

    @PreDestroy
    public void shutDown() {
        System.out.println("Кавоварка вимикається...");
    }
}

Коли Spring завершує роботу застосунку, метод shutDown буде викликано автоматично.


4. Налаштовуємо власні методи для життєвого циклу

Іноді стандартних методів недостатньо, і потрібна додаткова гнучкість. Spring дає два способи, як додати свої методи для запуску і завершення роботи bean'ів.

Визначення методів у конфігурації Java

При використанні анотації @Bean можна вказати користувацькі методи для ініціалізації і завершення роботи.

Приклад:


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public CoffeeMaker coffeeMaker() {
        return new CoffeeMaker();
    }
}

class CoffeeMaker {

    public void init() {
        System.out.println("Кавоварка готова до роботи!");
    }

    public void destroy() {
        System.out.println("Кавоварка вимикається...");
    }
}

Під час ініціалізації bean'а Spring викличе метод init, а при завершенні роботи — метод destroy.


Реалізація інтерфейсів InitializingBean і DisposableBean

Якщо віддаєте перевагу використовувати інтерфейси, Spring надає два варіанти:

  • InitializingBean — для методів ініціалізації.
  • DisposableBean — для методів завершення роботи.

Приклад:


import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class CoffeeMaker implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() {
        System.out.println("Кавоварка готова до роботи! (Через InitializingBean)");
    }

    @Override
    public void destroy() {
        System.out.println("Кавоварка вимикається... (Через DisposableBean)");
    }
}

Програмісти часто жартують: "Якщо у вас інтерфейс для всього — значить, ви пишете на Java!". У Spring було так само, але з появою анотацій @PostConstruct і @PreDestroy розробники стали рідше використовувати інтерфейси.

5. Життєвий цикл Spring Beans на практиці

Тепер давайте подивимось повний приклад на основі анотацій. Створимо клас CoffeeMaker з допомогою анотації @Component і налаштуємо його життєвий цикл.


import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class CoffeeMaker {
    @PostConstruct
    public void heatUp() {
        System.out.println("Кавоварка нагрівається...");
    }

    @PreDestroy
    public void shutDown() {
        System.out.println("Кавоварка вимикається...");
    }

    public void brewCoffee() {
        System.out.println("Готуємо каву!");
    }
}

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AppConfig.class);

        CoffeeMaker coffeeMaker = context.getBean(CoffeeMaker.class);
        coffeeMaker.brewCoffee();

        context.close();
    }
}

@Configuration
@ComponentScan("com.example")
class AppConfig {}

Вивід у консоль:


Кавоварка нагрівається...
Готуємо каву!
Кавоварка вимикається...

Зверніть увагу, що метод heatUp запускається автоматично після створення об'єкта, а метод shutDown — перед завершенням роботи.


6. Практичні поради

  1. Використовуйте @PostConstruct і @PreDestroy, якщо є така можливість. Ці анотації прості, зрозумілі і спеціально створені для роботи з життєвим циклом.
  2. Уникайте складної логіки в методах ініціалізації або завершення. Методи, позначені цими анотаціями, краще використовувати для налаштування, перевірки або реєстрації необхідних компонентів.
  3. Слідкуйте за ресурсами. Якщо ваш bean використовує зовнішні ресурси (наприклад, базу даних, з'єднання з мережею), обов'язково звільняйте їх у методі завершення роботи.
  4. Регулярно тестуйте життєвий цикл. Особливо це важливо в застосунках зі складною конфігурацією.

Коли ви розумієте життєвий цикл Spring Beans і те, як керувати їх створенням, ініціалізацією і завершенням роботи, ви починаєте значно краще контролювати поведінку вашого застосунку. Ці знання актуальні на всіх етапах розробки — від створення маленьких утиліт до проєктування масштабованих мікросервісів.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ