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:
- Was ist externe Konfiguration?
- Warum sollte Konfiguration nicht hardcodiert sein?
- Was ist
application.properties? - Was ist
application.yml? - Was ist der Unterschied zwischen Properties und YAML?
- Wie lädt Spring Boot Konfiguration?
- Was ist
@Value? - Was ist
@ConfigurationProperties? - Wann solltest du
@Valuenutzen? - Wann solltest du
@ConfigurationPropertiesnutzen? - Wie überschreiben Umgebungsvariablen Konfigurationsdateien?
- 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.
@Configurationmarkiert eine Klasse als Quelle von Bean-Definitionen.@Beanmarkiert 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 |
|---|---|---|
| Stil | flache Key-Value-Paare | hierarchisch |
| Lesbarkeit | gut für kleine Config | besser für gruppierte Config |
| Einrückungssensitiv | nein | ja |
| Üblich in Spring Boot | ja | ja |
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:
- Die Property hinzufügen.
- Einen Standardwert nutzen.
@ConfigurationPropertiesnutzen.- 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
@Valuefor one value. Use@ConfigurationPropertiesfor 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ür | einzelner Wert | gruppierte Config |
| Typsichere Gruppierung | schwach | stark |
| Validation | weniger sauber | sehr gut |
| Metadata-Unterstützung | begrenzt | gut |
| Relaxed Binding | begrenzt vs. Config Props | stark |
| Immutability | möglich, aber unübersichtlich | sauber mit Records |
| Beispiel | @Value("${app.name}") | AppProperties-Klasse |
Merksatz:
@Valueis for small one-off values.@ConfigurationPropertiesis 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:
@ConfigurationPropertiesdescribes 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:
@Valueworks 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:
@ConfigurationPropertieshas stronger relaxed binding support than direct@Valueplaceholders.
48. Praxisfrage: Wie sieht man die aktive Config?
Nützliche Wege:
- Startup-Logs prüfen.
- Actuator
/actuator/envnutzen. - Actuator
/actuator/configpropsnutzen. - Ausgewählte Properties sicher loggen.
- 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
@Valueand@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
@Valueannotations?
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.propertiesist flache Key-Value-Config.application.ymlist hierarchische Config.@Valueinjiziert einen Konfigurationswert.@Value("${key:default}")liefert einen Standardwert.- Fehlende
@Value-Placeholders können den Anwendungsstart verhindern. @ConfigurationPropertiesbindet gruppierte Config an ein Java-Objekt.@ConfigurationPropertiesist besser für strukturierte und typsichere Config.@ConfigurationProperties-Klassen müssen registriert werden.@ConfigurationPropertiesScankann Properties-Klassen scannen.@EnableConfigurationPropertieskann 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.
@Valuefunktioniert nur in von Spring verwalteten Beans.