← Назад к вопросам

Какая задача у контекста?

2.3 Middle🔥 201 комментариев
#Spring Boot и Spring Data#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Задача Spring Context (ApplicationContext)

ApplicationContext — это ключевой компонент в Spring Framework, отвечающий за управление жизненным циклом объектов приложения и внедрение зависимостей.

1. Основное назначение ApplicationContext

Spring Context выполняет несколько критических функций:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ContextExample {
    public static void main(String[] args) {
        // Создание контекста - это главное действие при старте приложения
        ApplicationContext context = new AnnotationConfigApplicationContext(
            AppConfig.class
        );
        
        // Контекст содержит все бины
        System.out.println("Созданы бины: " + context.getBeanDefinitionCount());
        
        // Извлечение бина из контекста
        UserService userService = context.getBean(UserService.class);
        userService.createUser("John");
    }
}

2. Основные задачи контекста

A) Создание и управление жизненным циклом объектов (бинов)

@Configuration
public class AppConfig {
    
    // Бин создается при инициализации контекста
    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
    
    @Bean
    public UserService userService(UserRepository repository) {
        return new UserService(repository);
    }
}

// Бины создаются один раз при старте и переиспользуются
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(
            AppConfig.class
        );
        
        UserService service1 = context.getBean(UserService.class);
        UserService service2 = context.getBean(UserService.class);
        
        // service1 == service2 (singleton по умолчанию)
        System.out.println(service1 == service2); // true
    }
}

B) Внедрение зависимостей (Dependency Injection)

@Component
public class UserService {
    private final UserRepository repository;
    private final EmailService emailService;
    
    // Контекст автоматически внедряет зависимости
    public UserService(UserRepository repository, EmailService emailService) {
        this.repository = repository;
        this.emailService = emailService;
    }
}

@Component
public class UserRepository {
    // База данных
}

@Component
public class EmailService {
    // Отправка писем
}

// Контекст решает все зависимости при создании UserService

C) Инициализация и уничтожение бинов

@Component
public class DatabaseConnection {
    
    @PostConstruct
    public void init() {
        System.out.println("Подключение к БД...");
        // Вызывается контекстом при создании бина
    }
    
    @PreDestroy
    public void close() {
        System.out.println("Закрытие соединения...");
        // Вызывается контекстом при завершении приложения
    }
}

3. Основные типы контекстов

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

// 1. AnnotationConfigApplicationContext - для простых приложений
ApplicationContext context1 = new AnnotationConfigApplicationContext(
    AppConfig.class
);

// 2. ClassPathXmlApplicationContext - на основе XML конфигурации
ApplicationContext context2 = new org.springframework.context.support
    .ClassPathXmlApplicationContext("applicationContext.xml");

// 3. FileSystemXmlApplicationContext - из файла системы
ApplicationContext context3 = new org.springframework.context.support
    .FileSystemXmlApplicationContext("/path/to/config.xml");

4. Получение информации из контекста

public class ContextInspection {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(
            AppConfig.class
        );
        
        // Получение количества бинов
        int beanCount = context.getBeanDefinitionCount();
        System.out.println("Всего бинов: " + beanCount);
        
        // Получение всех имен бинов
        String[] beanNames = context.getBeanDefinitionNames();
        for (String name : beanNames) {
            System.out.println("Бин: " + name);
        }
        
        // Получение бина по классу
        UserService service = context.getBean(UserService.class);
        
        // Получение бина по имени
        UserService namedService = (UserService) context.getBean("userService");
        
        // Проверка существования бина
        if (context.containsBean("userService")) {
            System.out.println("Бин userService существует");
        }
        
        // Получение типа бина
        Class<?> beanType = context.getType("userService");
        
        // Получение aliases
        String[] aliases = context.getAliases("userService");
    }
}

5. Иерархия контекстов (в веб-приложениях)

// В Spring MVC есть ROOT контекст и SERVLET контекст
// ROOT контекст - общие бины (service, repository, config)
// SERVLET контекст - специфичные для контроллеров

// ROOT контекст
public class RootConfig {
    @Bean
    public UserService userService() { return new UserService(); }
}

// SERVLET контекст (детский контекст)
public class WebConfig {
    @Bean
    public UserController userController(UserService userService) {
        return new UserController(userService);
    }
}

// Детский контекст может видеть бины родительского,
// но не наоборот

6. Жизненный цикл бина в контексте

public class BeanLifecycle {
    
    static class MyBean {
        public MyBean() {
            System.out.println("1. Конструктор вызван");
        }
        
        @PostConstruct
        public void init() {
            System.out.println("2. @PostConstruct вызван");
            // Инициализация ресурсов
        }
        
        public void customInit() {
            System.out.println("3. initMethod (из @Bean конфига)");
        }
        
        @PreDestroy
        public void destroy() {
            System.out.println("4. @PreDestroy вызван");
        }
    }
    
    @Configuration
    static class Config {
        @Bean(initMethod = "customInit")
        public MyBean myBean() {
            return new MyBean();
        }
    }
}

// Порядок инициализации:
// 1. Конструктор
// 2. Внедрение зависимостей
// 3. @PostConstruct
// 4. initMethod

7. Практический пример - полный жизненный цикл

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    
    @Bean
    public DataSource dataSource() {
        return new DataSource();
    }
}

public class Main {
    public static void main(String[] args) {
        // 1. Создание контекста
        ApplicationContext context = new AnnotationConfigApplicationContext(
            AppConfig.class
        );
        // Контекст создан, все бины инициализированы
        
        // 2. Использование приложения
        UserService userService = context.getBean(UserService.class);
        userService.createUser("Alice");
        
        // 3. Завершение (если ApplicationContext extends Closeable)
        if (context instanceof org.springframework.context.support
            .AbstractApplicationContext) {
            ((org.springframework.context.support.AbstractApplicationContext)
             context).close();
            // @PreDestroy методы вызваны, ресурсы освобождены
        }
    }
}

Главные задачи контекста (резюме)

  • Создание бинов из конфигурации
  • Управление зависимостями между бинами
  • Инициализация ресурсов через @PostConstruct
  • Очистка ресурсов через @PreDestroy
  • Управление жизненным циклом от создания до уничтожения
  • Хранилище всех бинов приложения
  • Интеграция различных компонентов в единое целое