Zum Hauptinhalt springen

Woche 2, Tag 2 — Externe Konfiguration, @Value und @ConfigurationProperties

Ziel

Heute willst du verstehen, wie Spring Konfiguration von außerhalb des Codes liest.

Die Kernfragen:

  1. Was ist externe Konfiguration?
  2. Warum sollte Konfiguration nicht hardcodiert sein?
  3. Was ist application.properties?
  4. Was ist application.yml?
  5. Was ist der Unterschied zwischen Properties und YAML?
  6. Wie lädt Spring Boot Konfiguration?
  7. Was ist @Value?
  8. Was ist @ConfigurationProperties?
  9. Wann solltest du @Value nutzen?
  10. Wann solltest du @ConfigurationProperties nutzen?
  11. Wie überschreiben Umgebungsvariablen Konfigurationsdateien?
  12. Welche typischen Prüfungsfallen gibt es?

1. Kurz-Wiederholung aus Woche 2, Tag 1

In Tag 1 hast du gelernt:

  • Java-Konfiguration definiert Spring Beans mit Java-Code.
  • @Configuration markiert eine Klasse als Quelle von Bean-Definitionen.
  • @Bean markiert eine Methode, deren Rückgabewert zu einer Spring Bean wird.
  • Vollständige @Configuration-Klassen werden per Proxy behandelt.
  • @Configuration(proxyBeanMethods = false) deaktiviert das Proxying.
  • Bevorzuge @Bean-Methodenparameter gegenüber direkten Methodenaufrufen.

Merksatz:


@Configuration defines bean recipes.
@Bean returns objects that become Spring beans.

Heute lernst du, wie du Werte von außerhalb des Java-Codes konfigurierst.


2. Was ist externe Konfiguration?

Externe Konfiguration bedeutet:

Werte, die sich zwischen Umgebungen unterscheiden, sollten außerhalb des Java-Codes liegen.

Beispiele:


database URL
database username
database password
server port
JWT secret
API base URL
feature flags
email provider
file upload limits
logging level
active profile

Schlecht:


private String apiUrl = "https://api.production.com";

Besser:


external-api:
base-url: https://api.production.com

Dann liest Spring diesen Wert.


3. Warum externe Konfiguration wichtig ist

Hardcodierte Werte sind schlecht, weil:

  • der Code für jede Umgebung geändert werden muss
  • Secrets versehentlich committed werden können
  • Tests schwieriger werden
  • Deployments weniger flexibel werden
  • Docker/Kubernetes/Cloud-Deployments schwieriger werden
  • Produktionskonfiguration nicht im Quellcode liegen sollte

Gute Konfiguration trennt:


code = stable logic
configuration = environment-specific values

Merksatz:

Code soll Verhalten beschreiben. Konfiguration soll umgebungsspezifische Werte beschreiben.


4. Typische Umgebungen

Die meisten echten Anwendungen haben mehrere Umgebungen.


local
dev
test
staging
prod
docker
ci

Beispiel:

Lokale Datenbank:


jdbc:postgresql://localhost:5432/app

Produktionsdatenbank:


jdbc:postgresql://prod-db:5432/app

Der Code soll gleich bleiben.

Nur die Konfiguration ändert sich.


5. application.properties

Spring Boot kann Konfiguration lesen aus:


application.properties

Beispiel:


server.port=8080

app.name=klarsync
app.max-tasks-per-user=50

external-api.base-url=https://api.example.com
external-api.timeout-seconds=10

Dieses Format nutzt Key-Value-Paare.


6. application.yml

Spring Boot kann auch lesen:


application.yml

Beispiel:


server:
port: 8080

app:
name: klarsync
max-tasks-per-user: 50

external-api:
base-url: https://api.example.com
timeout-seconds: 10

YAML ist hierarchisch.

Es ist oft leichter lesbar für gruppierte Konfiguration.


7. Properties vs YAML

Beides ist gültig.

Properties


app.name=klarsync
app.max-tasks-per-user=50
app.email.enabled=true

YAML


app:
name: klarsync
max-tasks-per-user: 50
email:
enabled: true

Vergleich:

Thema.properties.yml
Stilflache Key-Value-Paarehierarchisch
Lesbarkeitgut für kleine Configbesser für gruppierte Config
Einrückungssensitivneinja
Üblich in Spring Bootjaja

Wichtig:

Nutze nicht beides für dieselben Werte, es sei denn, du verstehst die Priorität klar.


8. Typischer YAML-Fehler

YAML hängt von der Einrückung ab.

Korrekt:


app:
name: klarsync
email:
enabled: true

Falsch:


app:
name: klarsync
email:
enabled: true

YAML-Einrückung ist wichtig.

Die Prüfung testet YAML-Syntax vielleicht nicht tief — aber echte Projekte brechen oft wegen schlechter Einrückung.


9. Woher lädt Spring Boot Konfiguration?

Spring Boot kann Konfiguration aus vielen Quellen lesen.

Typische Quellen:


application.properties
application.yml
profile-specific files
environment variables
command-line arguments
system properties
config data locations

Beispiele:


application-dev.yml
application-test.yml
application-prod.yml

Command-Line-Beispiel:


java -jar app.jar --server.port=9090

Umgebungsvariablen-Beispiel:


SERVER_PORT=9090 java -jar app.jar

10. Wichtige Idee: Externe Config kann Datei-Config überschreiben

Beispieldatei:


server:
port: 8080

Start mit:


java -jar app.jar --server.port=9090

Ergebnis:


server.port = 9090

Der Command-Line-Wert überschreibt den Datei-Wert.

Merksatz:

Spätere und höher priorisierte externe Konfiguration kann Werte aus application.yml überschreiben.


11. Warum das in Produktion nützlich ist

In Produktion willst du die App nicht neu bauen, nur um einen Port oder eine Datenbank-URL zu ändern.

Beispiel:


SPRING_DATASOURCE_URL=jdbc:postgresql://prod-db:5432/app
SPRING_DATASOURCE_USERNAME=app_user
SPRING_DATASOURCE_PASSWORD=secret
java -jar app.jar

Dasselbe Application-JAR.

Andere Umgebungskonfiguration.


12. Umgebungsvariablen und Relaxed Binding

Spring Boot unterstützt Relaxed Binding.

Das bedeutet: Verschiedene Namensstile können auf dieselbe Property mappen.

Beispiel-Property:


external-api.base-url=https://api.example.com

Umgebungsvariable:


EXTERNAL_API_BASE_URL=https://api.example.com

Diese können auf denselben Konfigurationswert mappen.

Beispiele, die oft zusammen mappen:


external-api.base-url
externalApi.baseUrl
external_api_base_url
EXTERNAL_API_BASE_URL

Merksatz:

Spring Boot Relaxed Binding erlaubt verschiedene Property-Namensstile, die auf dasselbe Konfigurationsfeld binden.


13. Was ist @Value?

@Value injiziert einen einzelnen Konfigurationswert.

Beispiel:


app:
name: klarsync

Java:


@Component
public class AppInfo {

@Value("${app.name}")
private String appName;
}

Spring liest:


app.name

und injiziert ihn in:


appName

14. @Value mit Constructor Injection

Field Injection funktioniert — Constructor Injection ist aber besser.

Besser:


@Component
public class AppInfo {

private final String appName;

public AppInfo(@Value("${app.name}") String appName) {
this.appName = appName;
}
}

Das macht die Abhängigkeit explizit.


15. Standardwert mit @Value

Du kannst einen Standardwert angeben.


@Value("${app.name:default-app}")
private String appName;

Bedeutung:


Use app.name if it exists.
Otherwise use default-app.

Beispiel:


@Value("${external-api.timeout-seconds:5}")
private int timeoutSeconds;

Fehlt die Property, injiziert Spring:


5

16. Was passiert, wenn eine @Value-Property fehlt?

Beispiel:


@Value("${app.name}")
private String appName;

Existiert app.name nicht, schlägt Spring beim Start meist fehl.

Typischer Fehler:


Could not resolve placeholder 'app.name'

Lösungen:

  1. Die Property hinzufügen.
  2. Einen Standardwert nutzen.
  3. @ConfigurationProperties nutzen.
  4. Die Konfiguration auf andere Weise optional machen.

17. @Value für einfache Werte

@Value ist nützlich für einfache Einzelwerte.

Beispiel:


@Component
public class ReportService {

private final int maxReportSize;

public ReportService(
@Value("${report.max-size:100}") int maxReportSize
) {
this.maxReportSize = maxReportSize;
}
}

Das ist okay — es ist nur ein Wert.


18. Problem mit zu vielen @Value-Feldern

Schlecht:


@Component
public class ExternalApiClient {

public ExternalApiClient(
@Value("${external-api.base-url}") String baseUrl,
@Value("${external-api.timeout-seconds}") int timeoutSeconds,
@Value("${external-api.retry-count}") int retryCount,
@Value("${external-api.enabled}") boolean enabled
) {
}
}

Das funktioniert — wird aber unübersichtlich.

Besser:


@ConfigurationProperties(prefix = "external-api")
public class ExternalApiProperties {
private String baseUrl;
private int timeoutSeconds;
private int retryCount;
private boolean enabled;
}

Merksatz:

Use @Value for one value. Use @ConfigurationProperties for grouped values.


19. Was ist @ConfigurationProperties?

@ConfigurationProperties bindet eine Gruppe zusammengehöriger Properties an ein Java-Objekt.

Beispiel-Config:


external-api:
base-url: https://api.example.com
timeout-seconds: 10
retry-count: 3
enabled: true

Java-Klasse:


@ConfigurationProperties(prefix = "external-api")
public class ExternalApiProperties {

private String baseUrl;
private int timeoutSeconds;
private int retryCount;
private boolean enabled;

public String getBaseUrl() {
return baseUrl;
}

public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}

public int getTimeoutSeconds() {
return timeoutSeconds;
}

public void setTimeoutSeconds(int timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
}

public int getRetryCount() {
return retryCount;
}

public void setRetryCount(int retryCount) {
this.retryCount = retryCount;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

Spring bindet:


external-api.base-url -> baseUrl
external-api.timeout-seconds -> timeoutSeconds
external-api.retry-count -> retryCount
external-api.enabled -> enabled

20. @ConfigurationProperties registrieren

Eine @ConfigurationProperties-Klasse muss als Bean registriert werden.

Typische Wege:

Option 1 — @Component hinzufügen


@Component
@ConfigurationProperties(prefix = "external-api")
public class ExternalApiProperties {
}

Einfach und üblich.


Option 2 — @EnableConfigurationProperties nutzen


@Configuration
@EnableConfigurationProperties(ExternalApiProperties.class)
public class ExternalApiConfig {
}

Dann:


@ConfigurationProperties(prefix = "external-api")
public class ExternalApiProperties {
}

Das ist sauber — die Properties-Klasse braucht kein @Component.


Option 3 — @ConfigurationPropertiesScan nutzen

Auf der Main-Klasse:


@SpringBootApplication
@ConfigurationPropertiesScan
public class MyApplication {
}

Dann scannt Spring nach @ConfigurationProperties-Klassen.


21. @ConfigurationProperties in einem Service nutzen

Properties-Klasse:


@Component
@ConfigurationProperties(prefix = "external-api")
public class ExternalApiProperties {

private String baseUrl;
private int timeoutSeconds;

public String getBaseUrl() {
return baseUrl;
}

public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}

public int getTimeoutSeconds() {
return timeoutSeconds;
}

public void setTimeoutSeconds(int timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
}
}

Service:


@Service
public class ExternalApiClient {

private final ExternalApiProperties properties;

public ExternalApiClient(ExternalApiProperties properties) {
this.properties = properties;
}

public void callApi() {
System.out.println(properties.getBaseUrl());
}
}

Das ist sauberer als viele @Value-Annotationen.


22. Constructor Binding mit Records

Modernes Spring Boot funktioniert gut mit unveränderlicher Konfiguration.

Beispiel-YAML:


external-api:
base-url: https://api.example.com
timeout-seconds: 10
retry-count: 3

Java Record:


@ConfigurationProperties(prefix = "external-api")
public record ExternalApiProperties(
String baseUrl,
int timeoutSeconds,
int retryCount
) {
}

Registriere es mit:


@SpringBootApplication
@ConfigurationPropertiesScan
public class MyApplication {
}

Das ist sauber und unveränderlich.


23. Warum unveränderliche Konfiguration schön ist

Unveränderliche Konfiguration bedeutet: Werte können nach der Objekterstellung nicht mehr geändert werden.

Vorteile:

  • sicherer
  • leichter zu durchdenken
  • keine Setter nötig
  • besser mit Constructor Injection
  • weniger versehentliche Mutation

Beispiel:


public record AppProperties(
String name,
int maxTasks
) {
}

Merksatz:

Configuration values should usually be read once and treated as immutable.


24. @ConfigurationProperties mit Validation

Du kannst Konfigurationswerte validieren.

Beispiel:


@ConfigurationProperties(prefix = "external-api")
@Validated
public class ExternalApiProperties {

@NotBlank
private String baseUrl;

@Min(1)
private int timeoutSeconds;

// getters and setters
}

Ist die Config ungültig, schlägt die App beim Start fehl.

Das ist gut.

Es bedeutet: Schlechte Produktionskonfiguration wird früh erkannt.


25. Validation mit Record


@ConfigurationProperties(prefix = "external-api")
@Validated
public record ExternalApiProperties(
@NotBlank String baseUrl,
@Min(1) int timeoutSeconds
) {
}

Config:


external-api:
base-url: ""
timeout-seconds: 0

Ergebnis:


Application fails to start because configuration is invalid.

Das ist gut für Produktionssicherheit.


26. @Value vs @ConfigurationProperties

Thema@Value@ConfigurationProperties
Am besten füreinzelner Wertgruppierte Config
Typsichere Gruppierungschwachstark
Validationweniger saubersehr gut
Metadata-Unterstützungbegrenztgut
Relaxed Bindingbegrenzt vs. Config Propsstark
Immutabilitymöglich, aber unübersichtlichsauber mit Records
Beispiel@Value("${app.name}")AppProperties-Klasse

Merksatz:

@Value is for small one-off values. @ConfigurationProperties is for structured configuration.


27. Beispiel: schlecht vs. gut

Schlecht:


@Service
public class JwtService {

public JwtService(
@Value("${jwt.secret}") String secret,
@Value("${jwt.expiration-minutes}") long expirationMinutes,
@Value("${jwt.issuer}") String issuer
) {
}
}

Gut:


@ConfigurationProperties(prefix = "jwt")
public record JwtProperties(
String secret,
long expirationMinutes,
String issuer
) {
}

Service:


@Service
public class JwtService {

private final JwtProperties jwtProperties;

public JwtService(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
}
}

28. Konfiguration für deine Klarsync-ähnliche App

Beispiel:


app:
name: klarsync
default-language: de
task:
max-open-tasks-per-user: 100
overdue-warning-days: 3

document:
upload:
max-file-size-mb: 20
allowed-types:
- pdf
- png
- jpg

external-api:
tax-office:
base-url: https://api.tax-office.example
timeout-seconds: 10

Properties-Klasse:


@ConfigurationProperties(prefix = "app")
public record AppProperties(
String name,
String defaultLanguage,
Task task
) {
public record Task(
int maxOpenTasksPerUser,
int overdueWarningDays
) {
}
}

Das gruppiert Config sauber.


29. Listen in @ConfigurationProperties

YAML:


document:
upload:
allowed-types:
- pdf
- png
- jpg

Java:


@ConfigurationProperties(prefix = "document.upload")
public record DocumentUploadProperties(
List<String> allowedTypes
) {
}

Spring bindet die YAML-Liste in List<String>.


30. Maps in @ConfigurationProperties

YAML:


app:
roles:
admin: ROLE_ADMIN
employee: ROLE_EMPLOYEE
client: ROLE_CLIENT

Java:


@ConfigurationProperties(prefix = "app")
public record AppProperties(
Map<String, String> roles
) {
}

Spring bindet:


admin -> ROLE_ADMIN
employee -> ROLE_EMPLOYEE
client -> ROLE_CLIENT

31. Typkonvertierung

Spring kann Konfigurationsstrings in viele Typen konvertieren.

Beispiele:


app:
timeout: 30s
max-file-size: 20MB
start-date: 2026-01-01

Java:


@ConfigurationProperties(prefix = "app")
public record AppProperties(
Duration timeout,
DataSize maxFileSize,
LocalDate startDate
) {
}

Spring Boot kann diese an passende Typen binden.

Das ist mächtig — und besser als nur Strings zu nutzen.


32. Typische Typen für Konfiguration

Nützliche Typen:


String
int / Integer
long / Long
boolean / Boolean
Duration
DataSize
LocalDate
List<T>
Map<K, V>
Enum
nested objects

Beispiel-Enum:


public enum StorageProvider {
LOCAL,
S3
}

YAML:


storage:
provider: S3

Properties:


@ConfigurationProperties(prefix = "storage")
public record StorageProperties(
StorageProvider provider
) {
}

33. Umgebungsvariablen für verschachtelte Config

YAML-Property:


external-api:
tax-office:
base-url: https://api.example.com

Äquivalente Umgebungsvariable:


EXTERNAL_API_TAX_OFFICE_BASE_URL=https://api.example.com

Spring Boot Relaxed Binding mappt das.


34. Command-Line-Argumente

Du kannst Config mit Command-Line-Argumenten überschreiben.


java -jar app.jar --server.port=9090 --app.name=demo

Das setzt:


server.port = 9090
app.name = demo

Command-Line-Argumente haben oft hohe Priorität.


35. System Properties

Du kannst auch Java System Properties übergeben.


java -Dserver.port=9090 -jar app.jar

Das setzt:


server.port = 9090

36. Typische Spring Boot Properties

Einige eingebaute Properties:


server.port=8080
spring.application.name=klarsync
spring.profiles.active=dev

spring.datasource.url=jdbc:postgresql://localhost:5432/app
spring.datasource.username=postgres
spring.datasource.password=secret

spring.jpa.hibernate.ddl-auto=validate
logging.level.org.springframework.security=DEBUG
management.endpoints.web.exposure.include=health,info,metrics

Du musst nicht alle Properties auswendig kennen.

Aber du solltest wissen: Spring Boot nutzt externe Properties, um viele eingebaute Features zu konfigurieren.


37. Konfiguration und Profiles

Profilspezifische Dateien:


application-dev.yml
application-test.yml
application-prod.yml

Beispiel:


## application-dev.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/app_dev

## application-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-db:5432/app_prod

Aktives Profil:


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

Profiles schauen wir in der nächsten Lektion genauer an.


38. Keine Secrets in Git ablegen

Schlecht:


jwt:
secret: my-production-secret

Besser:


JWT_SECRET=real-secret-from-server

Dann binde es an:


jwt:
secret: ${JWT_SECRET}

oder lass Relaxed Binding mappen:


JWT_SECRET=real-secret

auf:


jwt.secret

Wichtige Produktionsregel:

Do not commit real secrets into Git.


39. Placeholder-Syntax

Spring unterstützt Placeholders.


app:
name: ${APP_NAME:klarsync}

Bedeutung:


Use environment variable APP_NAME if it exists.
Otherwise use klarsync.

Beispiel:


external-api:
base-url: ${EXTERNAL_API_BASE_URL:https://api.default.com}

40. Praxisfrage: Welches soll ich nutzen?

@Value nutzen, wenn:


I need one simple value.

Beispiel:


public ReportService(@Value("${report.max-size:100}") int maxSize) {
}

@ConfigurationProperties nutzen, wenn:


I have a group of related values.

Beispiel:


jwt:
secret: abc
expiration-minutes: 60
issuer: klarsync

Nutze:


@ConfigurationProperties(prefix = "jwt")
public record JwtProperties(
String secret,
long expirationMinutes,
String issuer
) {
}

41. Praxisfrage: Ist @ConfigurationProperties automatisch eine Bean?

Nicht immer.

Diese Klasse:


@ConfigurationProperties(prefix = "jwt")
public record JwtProperties(String secret) {
}

muss trotzdem registriert werden.

Typische Wege:


@ConfigurationPropertiesScan

oder:


@EnableConfigurationProperties(JwtProperties.class)

oder:


@Component
@ConfigurationProperties(prefix = "jwt")

Typische Prüfungsfalle:

@ConfigurationProperties describes binding, but the class must also be registered as a bean.


42. Praxisfrage: Kann ich @Value in statischen Feldern nutzen?

Vermeide das.

Schlecht:


@Value("${app.name}")
private static String appName;

Spring injiziert in Bean-Instanzen — nicht in normalen statischen Zustand.

Besser:


@Component
public class AppInfo {

private final String appName;

public AppInfo(@Value("${app.name}") String appName) {
this.appName = appName;
}
}

Merksatz:

Spring dependency injection is instance-based, not static-field based.


43. Praxisfrage: Kann ich @Value in jeder Klasse nutzen?

Nur wenn die Klasse von Spring verwaltet wird.

Das funktioniert:


@Component
public class AppInfo {

public AppInfo(@Value("${app.name}") String appName) {
}
}

Das funktioniert nicht automatisch:


public class AppInfo {

@Value("${app.name}")
private String appName;
}

wenn du sie manuell erzeugst:


AppInfo appInfo = new AppInfo();

Weil Spring dieses Objekt nicht verwaltet.

Typische Prüfungsfalle:

@Value works only on Spring-managed beans.


44. Praxisfrage: Was passiert bei fehlgeschlagener Typkonvertierung?

Beispiel:


app:
max-tasks: abc

Java:


@Value("${app.max-tasks}")
private int maxTasks;

Spring kann "abc" nicht in int konvertieren.

Ergebnis:


Application fails to start.

Dasselbe gilt für @ConfigurationProperties.

Das ist gut — ungültige Config wird früh erkannt.


45. Praxisfrage: Kann @ConfigurationProperties verschachtelte Klassen nutzen?

Ja.

YAML:


app:
task:
max-open: 100
warning-days: 3

Java:


@ConfigurationProperties(prefix = "app")
public record AppProperties(
Task task
) {
public record Task(
int maxOpen,
int warningDays
) {
}
}

Das ist nützlich für strukturierte Config.


46. Praxisfrage: Was ist Relaxed Binding?

Relaxed Binding bedeutet: Spring Boot kann verschiedene Property-Namensstile an Java-Felder binden.

Beispiel-Java-Feld:


private int timeoutSeconds;

Kann binden von:


timeout-seconds
timeout_seconds
timeoutSeconds
TIMEOUT_SECONDS

Das ist besonders nützlich für Umgebungsvariablen.


47. Praxisfrage: @Value und Relaxed Binding

@Value ist direkter.

Beispiel:


@Value("${external-api.timeout-seconds}")
private int timeoutSeconds;

Der Placeholder muss dem Property-Key entsprechen.

@ConfigurationProperties ist besser für relaxed, strukturiertes Binding.

Merksatz für die Prüfung:

@ConfigurationProperties has stronger relaxed binding support than direct @Value placeholders.


48. Praxisfrage: Wie sieht man die aktive Config?

Nützliche Wege:

  1. Startup-Logs prüfen.
  2. Actuator /actuator/env nutzen.
  3. Actuator /actuator/configprops nutzen.
  4. Ausgewählte Properties sicher loggen.
  5. Tests nutzen.

Wichtig:

Do not log secrets.


49. Praxisfrage: Warum Konfiguration validieren?

Ohne Validation kann die App mit schlechten Werten starten.

Beispiel:


external-api:
timeout-seconds: 0

Das kann Runtime-Bugs verursachen.

Mit Validation:


@ConfigurationProperties(prefix = "external-api")
@Validated
public record ExternalApiProperties(
@Min(1) int timeoutSeconds
) {
}

Die App schlägt beim Start fehl.

Das ist besser als später in Produktion zu scheitern.


50. Typische Prüfungsfallen

Falle 1

@Value ist gut für einen Wert — nicht für große gruppierte Konfiguration.


Falle 2

@ConfigurationProperties-Klassen müssen als Beans registriert werden.


Falle 3

@Value funktioniert nur in von Spring verwalteten Beans.


Falle 4

Umgebungsvariablen können Werte aus Property-Dateien überschreiben.


Falle 5

Relaxed Binding hilft, Umgebungsvariablen auf Property-Namen zu mappen.


Falle 6

YAML-Einrückung ist wichtig.


Falle 7

Fehlende @Value-Placeholders können zum Startfehler führen — außer es gibt einen Standardwert.


Falle 8

Typkonvertierungsfehler können zum Startfehler führen.


Falle 9

Keine Produktions-Secrets in Git committen.


Falle 10

@ConfigurationProperties ist besser für gruppierte, typsichere, validierte Konfiguration.


51. Interview-Antwort

Frage:

What is external configuration in Spring Boot?

Gute Antwort:

Externe Konfiguration bedeutet, umgebungsspezifische Werte außerhalb des Java-Codes zu speichern — meist in application.properties, application.yml, Umgebungsvariablen, Command-Line-Argumenten oder profilspezifischen Dateien. So kann derselbe Anwendungscode in verschiedenen Umgebungen laufen: lokal, Test, Staging, Produktion. Spring Boot liest diese Konfigurationsquellen automatisch und nutzt sie zur Konfiguration der Anwendung.


52. Interview-Antwort

Frage:

What is the difference between @Value and @ConfigurationProperties?

Gute Antwort:

@Value injiziert einen einzelnen Konfigurationswert — zum Beispiel @Value("${app.name}"). Es ist einfach und nützlich für Einzelwerte. @ConfigurationProperties bindet eine Gruppe zusammengehöriger Properties an ein Java-Objekt. Es ist besser für strukturierte, typsichere Konfiguration — und funktioniert gut mit Validation, verschachtelten Objekten, Listen, Maps und unveränderlichen Records.


53. Interview-Antwort

Frage:

When would you use @ConfigurationProperties?

Gute Antwort:

Ich würde @ConfigurationProperties nutzen, wenn ich mehrere zusammengehörige Konfigurationswerte habe — zum Beispiel JWT-Einstellungen, externe API-Einstellungen, Upload-Einstellungen oder App-Feature-Einstellungen. Es hält Konfiguration organisiert, typsicher und leichter validierbar. Außerdem vermeidet es viele verstreute @Value-Annotationen in Services.


54. Interview-Antwort

Frage:

How do environment variables work with Spring Boot configuration?

Gute Antwort:

Spring Boot kann Konfiguration aus Umgebungsvariablen lesen. Dank Relaxed Binding kann eine Umgebungsvariable wie EXTERNAL_API_BASE_URL an eine Property wie external-api.base-url binden. Das ist nützlich in Docker, Cloud und Produktion — Werte können geändert werden, ohne die Anwendung neu zu bauen.


55. Interview-Antwort

Frage:

Why should secrets not be stored in application.yml?

Gute Antwort:

Echte Produktions-Secrets sollten nicht in Git committed werden — sie können leaken. Werte wie Datenbankpasswörter, JWT-Secrets, API-Keys und private Tokens sollten aus Umgebungsvariablen, Secret Managern oder Deployment-Konfiguration kommen. Die Anwendung kann diese Werte trotzdem über Spring Boot Konfiguration referenzieren.


56. Kleines Code-Übungsbeispiel

Erstelle dieses YAML:


jwt:
issuer: klarsync
expiration-minutes: 60

Erstelle dieses Properties-Record:


@ConfigurationProperties(prefix = "jwt")
public record JwtProperties(
String issuer,
long expirationMinutes
) {
}

Registriere es:


@SpringBootApplication
@ConfigurationPropertiesScan
public class MyApplication {
}

Injiziere es:


@Service
public class JwtService {

private final JwtProperties jwtProperties;

public JwtService(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
}
}

Frage:

Why is this cleaner than two @Value annotations?

Antwort:

Weil die JWT-Konfiguration in ein typsicheres Objekt gruppiert ist. Es ist leichter zu validieren, zu testen und zu warten.


57. Kleines Bug-Übungsbeispiel

Problem:


@ConfigurationProperties(prefix = "jwt")
public record JwtProperties(
String secret,
long expirationMinutes
) {
}

Service:


@Service
public class JwtService {

public JwtService(JwtProperties jwtProperties) {
}
}

Aber die Anwendung schlägt fehl:


No qualifying bean of type JwtProperties available

Frage:

What is probably missing?

Antwort:

Die Klasse JwtProperties ist nicht als Spring Bean registriert.

Mögliche Fixes:


@ConfigurationPropertiesScan

oder:


@EnableConfigurationProperties(JwtProperties.class)

oder hinzufügen:


@Component
@ConfigurationProperties(prefix = "jwt")

Übungsfragen

Frage 1

Was ist externe Konfiguration?

Antwort:

Externe Konfiguration bedeutet, umgebungsspezifische Werte außerhalb des Java-Codes zu speichern — zum Beispiel in application.yml, application.properties, Umgebungsvariablen, Command-Line-Argumenten oder profilspezifischen Dateien.


Frage 2

Warum sollte Konfiguration nicht hardcodiert sein?

Antwort:

Konfiguration sollte nicht hardcodiert sein, weil sich Werte oft zwischen Umgebungen ändern. Hardcoding macht Deployments weniger flexibel, Tests schwieriger — und kann Secrets im Quellcode offenlegen.


Frage 3

Was ist application.properties?

Antwort:

application.properties ist eine Spring Boot Konfigurationsdatei, die Key-Value-Konfiguration speichert — zum Beispiel server.port=8080.


Frage 4

Was ist application.yml?

Antwort:

application.yml ist eine Spring Boot Konfigurationsdatei, die Konfiguration im YAML-Format speichert — meist mit hierarchischer Struktur.


Frage 5

Was ist der Unterschied zwischen .properties und .yml?

Antwort:

.properties nutzt flache Key-Value-Paare. .yml nutzt hierarchische, einrückungsbasierte Struktur. Beides wird von Spring Boot unterstützt.


Frage 6

Was ist @Value?

Antwort:

@Value injiziert einen einzelnen Konfigurationswert in eine von Spring verwaltete Bean.


Frage 7

Wie kann ich einen Standardwert mit @Value angeben?

Antwort:

Du kannst einen Standardwert so angeben:


@Value("${app.name:default-app}")
private String appName;

Frage 8

Was passiert, wenn eine erforderliche @Value-Property fehlt?

Antwort:

Fehlt eine erforderliche @Value-Property und ist kein Standardwert gesetzt, schlägt die Anwendung meist beim Start fehl — mit einem Placeholder-Resolution-Fehler.


Frage 9

Was ist @ConfigurationProperties?

Antwort:

@ConfigurationProperties bindet eine Gruppe zusammengehöriger Konfigurationsproperties an ein Java-Objekt.


Frage 10

Wann sollte ich @Value nutzen?

Antwort:

Nutze @Value für einfache Einzelwerte.


Frage 11

Wann sollte ich @ConfigurationProperties nutzen?

Antwort:

Nutze @ConfigurationProperties für gruppierte, strukturierte, typsichere und validierte Konfiguration.


Frage 12

Erzeugt @ConfigurationProperties automatisch eine Spring Bean?

Antwort:

Nicht immer. Die @ConfigurationProperties-Klasse muss auch als Spring Bean registriert werden.


Frage 13

Wie registriere ich eine @ConfigurationProperties-Klasse?

Antwort:

Du kannst sie registrieren mit @ConfigurationPropertiesScan, @EnableConfigurationProperties oder indem du @Component zur Properties-Klasse hinzufügst.


Frage 14

Was ist Relaxed Binding?

Antwort:

Relaxed Binding bedeutet: Spring Boot kann verschiedene Namensstile binden — zum Beispiel base-url, baseUrl, base_url und BASE_URL — an dieselbe Java-Property.


Frage 15

Wie mappt diese Umgebungsvariable auf eine Property?


EXTERNAL_API_BASE_URL=https://api.example.com

Antwort:

EXTERNAL_API_BASE_URL kann mappen auf:


external-api.base-url

über Relaxed Binding.


Frage 16

Kann @ConfigurationProperties Listen und Maps binden?

Antwort:

Ja. @ConfigurationProperties kann Listen, Maps, verschachtelte Objekte, Enums, Durations, Data Sizes und andere Typen binden.


Frage 17

Warum ist Validation für Configuration Properties nützlich?

Antwort:

Validation ist nützlich, weil ungültige Konfiguration beim Start erkannt werden kann — statt Runtime-Bugs in Produktion zu verursachen.


Frage 18

Kann @Value in einer mit new erzeugten Klasse genutzt werden?

Antwort:

Nein, nicht automatisch. @Value funktioniert nur, wenn das Objekt von Spring verwaltet wird.


Frage 19

Warum sollten Secrets nicht in Git committed werden?

Antwort:

Secrets sollten nicht in Git committed werden — sie können leaken. Produktions-Secrets sollten aus Umgebungsvariablen, Secret Managern oder Deployment-Konfiguration kommen.


Frage 20

Was ist besser für diese Config: @Value oder @ConfigurationProperties?


jwt:
secret: abc
issuer: klarsync
expiration-minutes: 60

Antwort:

@ConfigurationProperties ist besser — jwt.secret, jwt.issuer und jwt.expiration-minutes sind zusammengehörige Werte und sollten in ein typsicheres Konfigurationsobjekt gruppiert werden.

Merksätze zum Mitnehmen

  • Externe Konfiguration hält umgebungsspezifische Werte außerhalb des Java-Codes.
  • Spring Boot liest Konfiguration aus Dateien, Umgebungsvariablen, Command-Line-Argumenten und mehr.
  • application.properties ist flache Key-Value-Config.
  • application.yml ist hierarchische Config.
  • @Value injiziert einen Konfigurationswert.
  • @Value("${key:default}") liefert einen Standardwert.
  • Fehlende @Value-Placeholders können den Anwendungsstart verhindern.
  • @ConfigurationProperties bindet gruppierte Config an ein Java-Objekt.
  • @ConfigurationProperties ist besser für strukturierte und typsichere Config.
  • @ConfigurationProperties-Klassen müssen registriert werden.
  • @ConfigurationPropertiesScan kann Properties-Klassen scannen.
  • @EnableConfigurationProperties kann Properties-Klassen explizit registrieren.
  • Relaxed Binding mappt verschiedene Namensstile auf Java-Felder.
  • Umgebungsvariablen können Datei-Konfiguration überschreiben.
  • Keine echten Secrets in Git committen.
  • Konfigurations-Validation erkennt schlechte Config beim Start.
  • @Value funktioniert nur in von Spring verwalteten Beans.