Что такое инициализация контекста (ApplicationContext) в Spring?

Ответ

Инициализация контекста в Spring — это процесс создания, настройки и подготовки к работе контейнера ApplicationContext, который является центральным компонентом Spring IoC, управляющим всеми бинами.

Основные этапы инициализации:

  1. Загрузка конфигурации: Контейнер считывает метаданные (XML, аннотации @ComponentScan, классы с @Configuration).
  2. Сканирование и регистрация определений бинов (BeanDefinition): На основе конфигурации создаются описания всех бинов.
  3. Создание экземпляров бинов (Instantiation): Для бинов с ленивой инициализацией (@Lazy) — по запросу, для остальных (singleton по умолчанию) — на этом этапе.
  4. Внедрение зависимостей (Population): Контейнер разрешает и инжектирует зависимости через конструкторы, сеттеры или поля (@Autowired).
  5. Инициализация бинов (Initialization):
    • Вызываются методы, помеченные @PostConstruct.
    • Если бин реализует InitializingBean, вызывается afterPropertiesSet().
    • Вызываются пользовательские методы init, указанные в @Bean(initMethod = "...").
  6. Контекст готов к работе.

Пример инициализации через Java-конфигурацию:

@Configuration
@ComponentScan("com.example.app") // 1. Указание на сканирование
public class AppConfig {
    @Bean // 2. Определение бина вручную
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

public class MainApp {
    public static void main(String[] args) {
        // Точка инициализации контекста
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        // Контекст прошел все этапы, бины готовы
        MyService service = ctx.getBean(MyService.class);
        service.start();
    }
}

Важные моменты:

  • Refresh: Метод refresh() в абстрактных реализациях контекста запускает полный цикл инициализации.
  • Типы контекстов: ClassPathXmlApplicationContext, AnnotationConfigApplicationContext, WebApplicationContext (для веб-приложений).
  • Закрытие: Вызов ctx.close() или registerShutdownHook() активирует фазу уничтожения бинов (вызов @PreDestroy).

Ответ 18+ 🔞

Ну, слушай, смотри, вот эта вся ваша инициализация контекста в Spring — это, блядь, как такой большой, сложный ритуал, когда ты пытаешься собрать шкаф из Икеи, только вместо гаечного ключа у тебя аннотации, а вместо кривых шведских инструкций — документация на Stack Overflow. Суть в том, что ты создаёшь этого самого ApplicationContext, главного завхоза, который будет всеми бинами рулить.

Как это, сука, происходит, по шагам:

  1. Загрузка конфигурации. Это когда завхоз приходит на склад и ищет чертежи. Где они? В XML, в аннотациях @ComponentScan, в классах с @Configuration. Находит — читает, блядь, глазами водит.
  2. Сканирование и регистрация. Он смотрит на чертежи и начинает составлять списки: «Так, стул — одна штука, стол — одна штука, вот эта хрень с пружинками — тоже бин». Это и есть BeanDefinition, описание того, что будет.
  3. Создание экземпляров. А вот тут начинается магия. Для обычных бинов (синглтонов) он сразу начинает всё пилить и собирать. А для ленивых (@Lazy) — откладывает на потом, типа «соберу, когда попросят, а то лень ебать».
  4. Внедрение зависимостей (Population). Ага, а тут самое интересное! Стул собрали, а у него, блядь, ножки отпадают. Надо прикрутить. Вот контейнер и бегает: «Тебе, стол, нужен стул? Держи! А тебе, стул, нужны винты? На, хули!» Через конструкторы, сеттеры или прямо в поля (@Autowired) засовывает.
  5. Инициализация бинов. Всё собрал, прикрутил. Теперь можно и покрасить, и лаком покрыть.
    • Сначала зовёт спеца по отделке — метод с @PostConstruct.
    • Потом, если бин сам знает, как его инициализировать (InitializingBean), даёт ему команду afterPropertiesSet().
    • Ну и если в конфиге какой-то свой, кастомный метод init прописан — запускает и его.
  6. Всё, пиздец, готово. Контекст стоит, сияет, бины на месте. Можно работать.

Вот смотри, как это в коде выглядит, чтоб ты, блядь, представил:

@Configuration
@ComponentScan("com.example.app") // 1. Говорим завхозу: «Ищи работников в этом районе!»
public class AppConfig {
    @Bean // 2. А этого работника нанимаем вручную, по знакомству
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

public class MainApp {
    public static void main(String[] args) {
        // А вот это — священный момент запуска всей этой ебалы!
        // Сказали «AnnotationConfigApplicationContext» — и понеслась!
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        // Всё, контекст проебался по всем этапам, бины готовы.
        MyService service = ctx.getBean(MyService.class); // Достаём бин со склада
        service.start(); // И используем, наконец-то!
    }
}

А теперь, сука, важные детали, чтоб не облажаться:

  • Refresh: Есть такой метод refresh(). Это типа кнопка «Перезагрузить всё к хуям» для абстрактных контекстов. Нажимаешь — и он заново весь этот цирк повторяет.
  • Типы контекстов: Их, блядь, несколько. ClassPathXmlApplicationContext — для староверов, которые в XML верят. AnnotationConfigApplicationContext — для современных пацанов. WebApplicationContext — для веб-девелоперов, у них своя атмосфера.
  • Закрытие: Всё хорошее когда-нибудь кончается. Вызвал ctx.close() или registerShutdownHook() — и контейнер пошёл всех бинов убивать, предварительно дав им попрощаться (вызвав @PreDestroy). Печально, но что поделать.