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

Как можно управлять контекстом в Spring Boot?

1.0 Junior🔥 101 комментариев
#Другое

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

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

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

# Как управлять контекстом в Spring Boot

Что такое ApplicationContext

ApplicationContext — это центральный объект Spring, который управляет всеми бинами, конфигурацией и жизненным циклом приложения.

1. Доступ к ApplicationContext через Autowiring

@Component
public class ContextAccessor {
    private final ApplicationContext applicationContext;
    
    // Внедрение ApplicationContext
    public ContextAccessor(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
    public void printAllBeans() {
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String name : beanNames) {
            System.out.println("Bean: " + name);
        }
    }
    
    public <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
    
    public Object getBean(String name) {
        return applicationContext.getBean(name);
    }
}

2. ApplicationContextAware (для полного доступа)

@Component
public class ContextAwareComponent implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.applicationContext = context;
    }
    
    public void displayContextInfo() {
        System.out.println("Application name: " + applicationContext.getApplicationName());
        System.out.println("Display name: " + applicationContext.getDisplayName());
        System.out.println("Bean count: " + applicationContext.getBeanDefinitionCount());
    }
}

3. Программное создание контекста

public class ManualContextCreation {
    public static void main(String[] args) {
        // Создание контекста вручную (без Spring Boot)
        ApplicationContext context = new ClassPathXmlApplicationContext(
            "application-context.xml"
        );
        
        UserService userService = context.getBean(UserService.class);
        userService.doSomething();
        
        // Закрытие контекста
        ((ClassPathXmlApplicationContext) context).close();
    }
}

4. Аннотационная конфигурация контекста

@Configuration
public class AppConfiguration {
    
    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
    
    @Bean
    public UserService userService(UserRepository repository) {
        return new UserService(repository);
    }
    
    @Bean
    public DataSource dataSource() {
        return DataSourceBuilder.create()
            .driverClassName("org.postgresql.Driver")
            .url("jdbc:postgresql://localhost/mydb")
            .username("user")
            .password("password")
            .build();
    }
}

5. Spring Boot ApplicationBuilder

public class CustomBootApplication {
    public static void main(String[] args) {
        ApplicationContext context = new SpringApplicationBuilder()
            .sources(MyApplication.class)
            .properties("spring.config.location=classpath:custom.properties")
            .bannerMode(Banner.Mode.OFF)
            .run(args);
        
        MyService service = context.getBean(MyService.class);
    }
}

@SpringBootApplication
public class MyApplication {}

6. Управление профилями (Profiles)

@Configuration
public class ProfileConfiguration {
    
    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        return DataSourceBuilder.create()
            .driverClassName("org.h2.Driver")
            .url("jdbc:h2:mem:testdb")
            .build();
    }
    
    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        return DataSourceBuilder.create()
            .driverClassName("org.postgresql.Driver")
            .url("jdbc:postgresql://prod-db:5432/db")
            .build();
    }
}

@Component
public class ProfileAwareService implements EnvironmentAware {
    private Environment environment;
    
    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
    
    public String getActiveProfile() {
        String[] profiles = environment.getActiveProfiles();
        return profiles.length > 0 ? profiles[0] : "default";
    }
}

7. Условная регистрация бинов (@Conditional)

@Component
@ConditionalOnProperty(
    name = "feature.caching.enabled",
    havingValue = "true"
)
public class CacheService {
    public void enableCaching() {
        System.out.println("Кеш включён");
    }
}

@Component
@ConditionalOnClass(name = "com.redis.Redis")
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        return new RedisTemplate<>();
    }
}

@Component
@ConditionalOnMissingBean(CacheService.class)
public class DefaultCacheService implements CacheService {}

8. Слушатели контекста (Context Listeners)

@Component
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("ApplicationContext инициализирован");
        ApplicationContext context = event.getApplicationContext();
        // Выполняем инициализацию
    }
}

@Component
public class AppCloseListener implements ApplicationListener<ContextClosedEvent> {
    
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        System.out.println("ApplicationContext закрывается");
        // Очистка ресурсов
    }
}

9. Фильтрация и получение бинов

@Component
public class BeanFinder {
    private final ApplicationContext context;
    
    public BeanFinder(ApplicationContext context) {
        this.context = context;
    }
    
    // Получить все бины определённого типа
    public void findAllOfType() {
        Map<String, UserService> beans = context.getBeansOfType(UserService.class);
        beans.forEach((name, bean) -> System.out.println(name + ": " + bean));
    }
    
    // Проверить наличие бина
    public void checkBean() {
        if (context.containsBean("userService")) {
            System.out.println("userService существует");
        }
    }
    
    // Получить бин по имени с типом
    public UserService getUserService() {
        return context.getBean("userService", UserService.class);
    }
    
    // Получить бины с аннотацией
    public void findAnnotatedBeans() {
        Map<String, Object> beans = context.getBeansWithAnnotation(Service.class);
        beans.forEach((name, bean) -> System.out.println(name));
    }
}

10. Refresh контекста (перезагрузка)

@Component
public class ContextManager {
    private final ConfigurableApplicationContext context;
    
    public ContextManager(ConfigurableApplicationContext context) {
        this.context = context;
    }
    
    public void reloadContext() {
        try {
            context.refresh();
            System.out.println("Контекст перезагружен");
        } catch (Exception e) {
            System.err.println("Ошибка при перезагрузке: " + e.getMessage());
        }
    }
    
    public void closeContext() {
        context.close();
        System.out.println("Контекст закрыт");
    }
    
    public boolean isRunning() {
        return context.isRunning();
    }
}

11. Иерархия контекстов (Parent-Child)

public class HierarchicalContextExample {
    public static void main(String[] args) {
        // Родительский контекст
        ApplicationContext parentContext = new ClassPathXmlApplicationContext(
            "parent-context.xml"
        );
        
        // Дочерний контекст
        ClassPathXmlApplicationContext childContext = 
            new ClassPathXmlApplicationContext(
                new String[]{"child-context.xml"},
                parentContext  // Передаём родителя
            );
        
        // Дочерний контекст может получать бины у родителя
        UserService userService = childContext.getBean(UserService.class);
    }
}

12. Event Publishing (событие в контексте)

// Определение события
public class UserCreatedEvent extends ApplicationEvent {
    private final User user;
    
    public UserCreatedEvent(Object source, User user) {
        super(source);
        this.user = user;
    }
    
    public User getUser() {
        return user;
    }
}

// Публикация события
@Service
public class UserService {
    private final ApplicationEventPublisher eventPublisher;
    
    public UserService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    
    public void createUser(User user) {
        repository.save(user);
        // Публикуем событие в контексте
        eventPublisher.publishEvent(new UserCreatedEvent(this, user));
    }
}

// Слушатель события
@Component
public class UserCreatedListener {
    @EventListener
    public void onUserCreated(UserCreatedEvent event) {
        User user = event.getUser();
        System.out.println("Новый пользователь: " + user.getName());
    }
}

13. Properties и Environment

@Component
public class PropertyManager {
    private final Environment environment;
    
    public PropertyManager(Environment environment) {
        this.environment = environment;
    }
    
    public String getDatabaseUrl() {
        return environment.getProperty("spring.datasource.url");
    }
    
    public int getDatabasePort() {
        return environment.getProperty("spring.datasource.port", Integer.class, 5432);
    }
    
    public boolean isProduction() {
        return environment.matchesProfiles("prod");
    }
}

14. Registry для регистрации бинов во время выполнения

@Component
public class DynamicBeanRegistry {
    private final ConfigurableApplicationContext context;
    
    public DynamicBeanRegistry(ConfigurableApplicationContext context) {
        this.context = context;
    }
    
    public void registerDynamicBean() {
        // Получаем registry
        DefaultListableBeanFactory factory = 
            (DefaultListableBeanFactory) context.getBeanFactory();
        
        // Регистрируем бин во время выполнения
        BeanDefinition beanDef = new RootBeanDefinition(MyDynamicService.class);
        factory.registerBeanDefinition("dynamicService", beanDef);
        
        MyDynamicService service = context.getBean("dynamicService", MyDynamicService.class);
    }
}

Best Practices

  1. Предпочитай Dependency Injection вместо прямого доступа к контексту
  2. Используй @Configuration для явной конфигурации бинов
  3. Профили для разных окружений (dev, test, prod)
  4. Event Publishing для слабо связанного взаимодействия
  5. Слушатели контекста для инициализации при старте
  6. Избегай Static contexts — используй внедрение зависимостей
  7. Properties and Environment для конфигурации
  8. Избегай множественного refresh() — это дорого