Как работать с переменными окружения (Environment) в Spring?

«Как работать с переменными окружения (Environment) в Spring?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Spring доступ к переменным окружения и свойствам приложения предоставляет интерфейс org.springframework.core.env.Environment. Это центральный абстракция для работы с конфигурацией.

Основные способы доступа:

  1. Инъекция через @Autowired:

    @Component
    public class MyService {
        @Autowired
        private Environment env;
    
        public void someMethod() {
            String dbUrl = env.getProperty("database.url");
            int port = env.getProperty("server.port", Integer.class, 8080); // Значение по умолчанию
            boolean isFeatureEnabled = env.getProperty("feature.flag", Boolean.class, false);
        }
    }
  2. Использование @Value:

    @Component
    public class MyComponent {
        // Получение значения свойства
        @Value("${api.key}")
        private String apiKey;
    
        // Со значением по умолчанию
        @Value("${cache.ttl:3600}")
        private int cacheTtl;
    
        // Получение переменной окружения ОС
        @Value("${JAVA_HOME}")
        private String javaHome;
    }

Источники свойств (PropertySources): Spring загружает свойства из различных источников в определенном порядке (поздние переопределяют ранние):

  1. Аргументы командной строки (--server.port=9090).
  2. Переменные окружения ОС (JAVA_HOME, DATABASE_URL).
  3. Файлы свойств из application-{profile}.properties / .yml.
  4. Файл application.properties / .yml.
  5. Аннотация @PropertySource.

Пример работы с профилями:

@Configuration
public class AppConfig {
    @Autowired
    Environment env;

    @Bean
    public DataSource dataSource() {
        // Создание бина в зависимости от активного профиля
        if (env.acceptsProfiles(Profiles.of("prod"))) {
            return createProductionDataSource();
        } else {
            return createEmbeddedDataSource();
        }
    }

    // Проверка наличия свойства
    public boolean isPropertySet(String key) {
        return env.containsProperty(key);
    }
}

Практические рекомендации:

  • Конфиденциальные данные: Храните пароли, API-ключи в переменных окружения, а не в файлах конфигурации, которые могут попасть в репозиторий.
  • 12-факторное приложение: Использование переменных окружения — один из ключевых принципов для конфигурации, зависящей от среды (dev, staging, prod).
  • Docker/Kubernetes: Конфигурация через env: в Docker Compose или ConfigMaps/Secrets в Kubernetes идеально ложится на эту модель Spring.