Spring Profiles – środowiska dev/test/prod

TL;DR: Spring Profiles pozwalają na różne konfiguracje aplikacji w zależności od środowiska (development, test, production). Jeden kod, różne ustawienia – bez modyfikowania źródeł przed każdym deployment.

Każdy programista zna ten problem: aplikacja działa lokalnie, ale po wdrożeniu na serwer przestaje działać. Często winne są różne konfiguracje – na lokalnej maszynie używasz bazy H2, na produkcji PostgreSQL. Spring Profiles rozwiązują ten problem elegancko.

W tym artykule dowiesz się jak skonfigurować różne środowiska w Spring bez zmieniania kodu źródłowego.

Dlaczego Spring Profiles są ważne

W profesjonalnym development masz co najmniej 3 środowiska: development (lokalne), test (staging) i production. Każde potrzebuje innych ustawień – innych baz danych, różnych poziomów logowania, innych adresów URL. Spring Profiles to standard industry w zarządzaniu konfiguracją.

Co się nauczysz:

  • Czym są Spring Profiles i dlaczego są potrzebne
  • Jak tworzyć profile dla różnych środowisk
  • Konfigurację przez application.properties i YAML
  • Aktywację profili na różne sposoby
  • Najlepsze praktyki w zarządzaniu środowiskami

Wymagania wstępne:

Podstawowa znajomość Spring Framework i Spring Boot. Doświadczenie z application.properties. Znajomość Maven/Gradle mile widziana.

Czym są Spring Profiles

Spring Profiles – mechanizm umożliwiający grupowanie konfiguracji i beanów pod nazwanymi profilami. Pozwala na aktywację różnych zestawów konfiguracji w zależności od środowiska.
Spring Profiles to jak przełącznik w mieszkaniu – jeden przełącznik, ale może włączać różne lampy. Jeden kod aplikacji, ale różne konfiguracje w zależności od tego, gdzie uruchamiasz aplikację.

Tworzenie profili przez properties

Struktura plików konfiguracyjnych

Spring Boot automatycznie wczytuje pliki konfiguracyjne według wzorca:

src/main/resources/
├── application.properties          # Domyślna konfiguracja
├── application-dev.properties      # Profil development
├── application-test.properties     # Profil test
└── application-prod.properties     # Profil production

Przykładowa konfiguracja

application.properties (konfiguracja domyślna):

# Konfiguracja wspólna dla wszystkich środowisk
app.name=Blog Application
app.version=1.0.0

# Domyślnie włącz profil development
spring.profiles.active=dev

application-dev.properties (development):

# Baza danych H2 w pamięci
spring.datasource.url=jdbc:h2:mem:devdb
spring.datasource.username=sa
spring.datasource.password=

# Włącz H2 console dla testów
spring.h2.console.enabled=true

# Debug level logging
logging.level.com.example=DEBUG
logging.level.org.springframework=INFO

# Wyłącz cache dla szybszego developmentu
spring.thymeleaf.cache=false

application-test.properties (testing):

# Baza testowa MySQL
spring.datasource.url=jdbc:mysql://test-server:3306/blog_test
spring.datasource.username=test_user
spring.datasource.password=test_pass

# Wyłącz DDL auto na testach
spring.jpa.hibernate.ddl-auto=validate

# Logowanie tylko błędów
logging.level.com.example=WARN
logging.level.org.springframework=WARN

# Test-specific ustawienia
app.feature.email-sending=false

application-prod.properties (production):

# Produkcyjna baza PostgreSQL
spring.datasource.url=jdbc:postgresql://prod-db:5432/blog_prod
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}

# Bezpieczne ustawienia JPA
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=false

# Minimal logging
logging.level.com.example=INFO
logging.level.org.springframework=WARN

# Production features
app.feature.email-sending=true
app.feature.analytics=true

Pro tip: Używaj zmiennych środowiskowych (${DB_PASSWORD}) dla wrażliwych danych w produkcji. Nigdy nie commituj prawdziwych haseł do repozytorium!

Profile-specific beany

Możesz tworzyć beany które są aktywne tylko w określonych profilach:

@Configuration
public class DatabaseConfig {
    
    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }
    
    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:postgresql://prod-db:5432/blog");
        config.setMaximumPoolSize(20);
        return new HikariDataSource(config);
    }
    
    @Bean
    @Profile({"test", "integration"})
    public DataSource testDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .setName("testdb")
            .build();
    }
}

Profile w komponentach

@Service
@Profile("dev")
public class MockEmailService implements EmailService {
    
    @Override
    public void sendEmail(String to, String subject, String body) {
        System.out.println("DEV: Wyślij email do " + to);
        System.out.println("Temat: " + subject);
    }
}

@Service
@Profile("prod")
public class SmtpEmailService implements EmailService {
    
    @Override
    public void sendEmail(String to, String subject, String body) {
        // Prawdziwe wysyłanie przez SMTP
        // ...
    }
}

Aktywacja profili

1. Przez application.properties

# Aktywuj jeden profil
spring.profiles.active=prod

# Aktywuj wiele profili
spring.profiles.active=prod,monitoring,security

2. Przez argumenty JVM

java -jar -Dspring.profiles.active=prod myapp.jar

3. Przez zmienne środowiskowe

export SPRING_PROFILES_ACTIVE=prod
java -jar myapp.jar

4. Programowo

@SpringBootApplication
public class BlogApplication {
    
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(BlogApplication.class);
        app.setAdditionalProfiles("prod");
        app.run(args);
    }
}

YAML configuration

Zamiast wielu plików properties możesz użyć jednego pliku YAML:

# application.yml
spring:
  profiles:
    active: dev

app:
  name: Blog Application
  version: 1.0.0

---
spring:
  profiles: dev
  datasource:
    url: jdbc:h2:mem:devdb
    username: sa
    password: 
  h2:
    console:
      enabled: true

logging:
  level:
    com.example: DEBUG

---
spring:
  profiles: prod
  datasource:
    url: jdbc:postgresql://prod-db:5432/blog
    username: ${DB_USER}
    password: ${DB_PASSWORD}

logging:
  level:
    com.example: INFO
Uwaga: W YAML indentacja ma znaczenie! Używaj spacji, nie tabów. Jeden błąd wcięcia może zepsuć całą konfigurację.

Najlepsze praktyki

Konwencje nazewnictwa

  • dev – lokalne środowisko developera
  • test/staging – środowisko testowe
  • prod – produkcja
  • integration – testy integracyjne

Bezpieczeństwo

Dobre praktyki bezpieczeństwa:

  • Używaj zmiennych środowiskowych dla haseł
  • Nigdy nie commituj prawdziwych danych produkcyjnych
  • Różne klucze API dla każdego środowiska
  • Wyłącz debug informacje na produkcji

Profile domyślne

# Profil używany gdy żaden nie jest aktywny
spring.profiles.default=dev
Typowy błąd: Zapominanie o ustawieniu profilu na produkcji. Aplikacja uruchamia się z profilem dev i łączy z lokalną bazą danych zamiast produkcyjnej!
Jak sprawdzić który profil jest aktywny?

W aplikacji: @Value("${spring.profiles.active}") lub przez Environment bean. W logach Spring Boot wypisuje aktywne profile podczas startu. Można też sprawdzić przez endpoint /actuator/env jeśli Actuator jest włączony.

Czy mogę mieć wiele aktywnych profili jednocześnie?

Tak! Można aktywować wiele profili: spring.profiles.active=prod,monitoring,security. Spring Boot wczyta konfigurację ze wszystkich aktywnych profili. Jeśli są konflikty, ostatni profil ma pierwszeństwo.

Co się stanie jeśli nie ustawię żadnego profilu?

Spring użyje profilu domyślnego określonego przez spring.profiles.default. Jeśli nie jest ustawiony, aplikacja uruchomi się bez żadnego profilu – tylko z application.properties.

Jak testować różne profile lokalnie?

W IDE ustaw VM options: -Dspring.profiles.active=test. W IntelliJ: Run Configuration → VM options. Możesz też tworzyć różne Run Configurations dla każdego profilu.

Czy profile działają z @ConfigurationProperties?

Tak! Profile świetnie współpracują z @ConfigurationProperties. Możesz mieć różne wartości properties dla każdego profilu i Spring automatycznie załaduje odpowiednie.

Jak zarządzać profilami w Docker?

Przez zmienną środowiskową: docker run -e SPRING_PROFILES_ACTIVE=prod myapp lub w docker-compose: environment: - SPRING_PROFILES_ACTIVE=prod

Przydatne zasoby

🚀 Zadanie dla Ciebie

Skonfiguruj profile dla aplikacji e-commerce:

1. Stwórz 3 profile: dev, test, prod
2. Dev: H2 database, debug logging, mock payment service
3. Test: MySQL database, warn logging, test payment service
4. Prod: PostgreSQL database, info logging, real payment service
5. Każdy profil ma mieć różne ustawienia email (dev – console, prod – SMTP)
6. Przetestuj uruchamianie aplikacji z różnymi profilami

Bonus: dodaj profil „docker” z konfiguracją dla kontenerów!

Spring Profiles to podstawowe narzędzie każdego Spring developera. Dzięki nim jedna aplikacja może działać w różnych środowiskach bez modyfikacji kodu. To klucz do profesjonalnego podejścia do deployment i konfiguracji.

Jakich profili używasz w swoich projektach? Masz jakieś ciekawe triki z konfiguracją? Podziel się w komentarzach!

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Przewijanie do góry