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

Какие знаешь способы внешней конфигурации приложения в Spring?

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

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

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

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

# Внешняя конфигурация в Spring

Внешняя конфигурация позволяет менять поведение приложения без перекомпиляции кода. Это критично для разных окружений (dev, staging, prod). Рассмотрим все способы.

1. application.properties и application.yml

Самый базовый и распространённый способ:

# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=update
server.port=8080
app.name=My Application
app.version=1.0.0

Или в YAML:

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret
  jpa:
    hibernate:
      ddl-auto: update

server:
  port: 8080

app:
  name: My Application
  version: 1.0.0

Использование в коде:

@Component
public class AppConfig {
    @Value("${app.name}")
    private String appName;
    
    @Value("${app.version:1.0}")
    private String appVersion; // С дефолтным значением
}

2. Profile-specific конфигурация

Разные файлы конфигурации для разных окружений:

src/main/resources/
├── application.properties          # Общие настройки
├── application-dev.properties      # Для разработки
├── application-staging.properties  # Для staging
└── application-prod.properties     # Для production

Запуск с профилем:

java -jar app.jar --spring.profiles.active=prod

Или в IDE:

@SpringBootTest(properties = "spring.profiles.active=test")
public class MyTest { }

3. Environment переменные (12-factor app)

Лучший способ для контейнеризации (Docker, Kubernetes):

export DB_URL=jdbc:mysql://prod-db:3306/mydb
export DB_USER=admin
export DB_PASSWORD=secret123
java -jar app.jar

И в application.properties:

spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}

В коде:

@Component
public class DatabaseConfig {
    @Value("${DB_URL}")
    private String dbUrl;
    
    public DatabaseConfig() {
        // Fallback если переменная не задана
        String url = System.getenv("DB_URL");
        if (url == null) {
            url = "jdbc:mysql://localhost:3306/mydb";
        }
    }
}

4. Command-line аргументы

Передача параметров при запуске:

java -jar app.jar --server.port=9090 --spring.datasource.url=jdbc:mysql://prod-db:3306/mydb

Или программно:

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(Application.class);
    app.setDefaultProperties(Collections.singletonMap("server.port", "9090"));
    app.run(args);
}

5. application-${profile}.properties

Комбинация профилей и переменных окружения:

# .env файл
APP_ENV=prod
DB_HOST=prod-db
DB_PORT=3306
DB_NAME=mydb

В application.properties:

spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}

6. @ConfigurationProperties (Рекомендуется)

Типобезопасная конфигурация:

# application.yml
app:
  database:
    host: localhost
    port: 3306
    name: mydb
    pool-size: 10
  mail:
    enabled: true
    from: noreply@example.com
    smtp-host: smtp.gmail.com

Java класс:

@Configuration
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private Database database;
    private Mail mail;
    
    // Getters и setters
    public static class Database {
        private String host;
        private int port;
        private String name;
        private int poolSize;
        
        // Getters и setters
    }
    
    public static class Mail {
        private boolean enabled;
        private String from;
        private String smtpHost;
        
        // Getters и setters
    }
}

@Component
public class ApplicationService {
    private final AppProperties props;
    
    public ApplicationService(AppProperties props) {
        this.props = props;
    }
    
    public void configure() {
        String dbUrl = "jdbc:mysql://" + props.getDatabase().getHost() + 
                       ":" + props.getDatabase().getPort() + "/" + 
                       props.getDatabase().getName();
        System.out.println("Подключение к БД: " + dbUrl);
    }
}

7. YAML с листами

# application.yml
app:
  servers:
    - name: primary
      host: 192.168.1.1
      port: 9000
    - name: secondary
      host: 192.168.1.2
      port: 9001

Java:

@ConfigurationProperties(prefix = "app")
public class ServerProperties {
    private List<Server> servers;
    
    public static class Server {
        private String name;
        private String host;
        private int port;
        // getters/setters
    }
}

8. Spring Cloud Config Server

Для микросервисов (централизованная конфигурация):

# bootstrap.yml
spring:
  cloud:
    config:
      uri: http://config-server:8888
      name: my-app
      profile: ${SPRING_PROFILES_ACTIVE}

Сервис:

@RestController
@RefreshScope
public class ConfigController {
    @Value("${app.name}")
    private String appName;
    
    @GetMapping("/config")
    public String getConfig() {
        return appName; // Обновляется при POST /actuator/refresh
    }
}

9. Конфигурационные классы Java

@Configuration
public class AppConfiguration {
    
    @Bean
    @ConditionalOnProperty(name = "mail.enabled", havingValue = "true")
    public MailService mailService() {
        return new MailService();
    }
    
    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        return createProductionDataSource();
    }
    
    @Bean
    @Profile({"dev", "test"})
    public DataSource testDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }
}

10. Приоритет источников конфигурации

Spring применяет конфигурацию в следующем порядке (от менее к более приоритетному):

  1. application.properties в jar'е
  2. application-{profile}.properties в jar'е
  3. application.properties вне jar'а (если есть в рабочей директории)
  4. application-{profile}.properties вне jar'а
  5. Environment переменные (система)
  6. Command-line аргументы
# Пример: Environment перекроет application.properties
export SERVER_PORT=9090
java -jar app.jar  # Будет использован порт 9090

Практический пример для production

# Dockerfile
FROM openjdk:17-slim

COPY target/app.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]
# docker-compose.yml
services:
  app:
    image: my-app:latest
    environment:
      SPRING_PROFILES_ACTIVE: prod
      DB_HOST: postgres
      DB_PORT: 5432
      DB_NAME: proddb
      DB_USER: admin
      DB_PASSWORD: ${DB_PASSWORD}  # Из .env
    depends_on:
      - postgres
  
  postgres:
    image: postgres:14
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}

Рекомендации по выбору

СпособКогда использоватьПлюсыМинусы
application.propertiesЛокальная разработкаПросто, быстроНе для production
ПрофилиРазные окруженияОрганизованноМного файлов
Environment переменныеDocker, K8sСтандарт, безопасноСложнее локальная разработка
@ConfigurationPropertiesСложная конфигурацияТипобезопасно, структурированоБольше кода
Spring Cloud ConfigМикросервисыЦентрализованноСложность, ещё один сервис

Best Practices

  • Используйте Environment переменные для секретов (passwords, tokens)
  • application.properties для дефолтов в разработке
  • @ConfigurationProperties для типобезопасности
  • Spring Cloud Config для микросервисов
  • Профили для разных окружений
  • НИКОГДА не коммитьте .env файлы с паролями