How it works
The explanation, with examples you can run.
Who wins
From weaker to stronger, the sources you will use most are:
application.ymlpackaged in the jarapplication-{profile}.ymlpackaged in the jar- The same two files outside the jar (for example in
./config/) - OS environment variables
- Java system properties (
-Dserver.port=9000) - Command-line arguments (
--server.port=9000)
Test annotations such as @SpringBootTest(properties = ...) and @DynamicPropertySource sit higher still. Environment variables use relaxed binding: SPRING_DATASOURCE_URL sets spring.datasource.url, because most shells don't allow dots in variable names.
Profiles
A profile is a named set of extra configuration. Activate it with spring.profiles.active (in any source, often SPRING_PROFILES_ACTIVE=prod), and Boot reads application-prod.yml on top of the base file. A single YAML file can hold several documents, each tied to a profile:
server: port: 8080app: payments: base-url: https://sandbox.example.com timeout: 2s---spring: config: activate: on-profile: prodapp: payments: base-url: https://api.example.comBeans can be limited to a profile with @Profile("dev"), but use that sparingly. Each profile-only bean is a code path that your tests may never take. Prefer the same beans everywhere with different property values.
Typed configuration
@Value("${app.payments.timeout}") works, but scatters string keys through the code. @ConfigurationProperties binds a whole prefix to one type, converts values (2s becomes a Duration) and can validate them at start-up:
@ConfigurationProperties(prefix = "app.payments")@Validatedpublic record PaymentProperties( @NotNull URI baseUrl, @DefaultValue("2s") Duration timeout) { } @SpringBootApplication@ConfigurationPropertiesScanpublic class App { }A record makes the settings immutable, and a missing or malformed value fails the start-up instead of the first payment.
Secrets
Keep secrets out of the jar and out of Git. Boot reads them from environment variables, from a config tree (a directory where each file name is a key, which is how Kubernetes mounts secrets: spring.config.import=optional:configtree:/run/secrets/), or from an external store through a library. The property names stay the same, so the code never knows where a value came from.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.