Typed, validated configuration catches mistakes at startup instead of in production traffic.
For a group of related settings, define a class or record annotated @ConfigurationProperties(prefix = "app.mail"). Boot binds app.mail.host, app.mail.port, app.mail.from and nested objects, lists, maps and Durations (timeout=5s) to it with type conversion, and you inject it like any bean. Register it with @ConfigurationPropertiesScan on the main class or @EnableConfigurationProperties(MailProperties.class).
Benefits over scattered @Values: one place for related settings, IDE auto-completion (with the spring-boot-configuration-processor dependency), and validation at startup with @Validated plus constraints: a missing host fails fast with a clear message.
Profiles select environment-specific configuration. application-dev.properties and application-prod.properties are loaded in addition to application.properties when the dev or prod profile is active, and override it. Activate with spring.profiles.active=prod (often via the environment variable SPRING_PROFILES_ACTIVE). A single YAML file can hold several profile sections separated by --- with spring.config.activate.on-profile.
Beans can be profile-specific with @Profile("dev"), for example a fake payment gateway in development. Keep profiles few and about environments; feature switches belong in normal properties.
Example
# application.properties
app.mail.host=smtp.example.com
app.mail.port=587
app.mail.timeout=5s
app.mail.recipients[0]=ops@example.com
# application-dev.properties (active with SPRING_PROFILES_ACTIVE=dev)
app.mail.host=localhost
// MailProperties.java
@Validated
@ConfigurationProperties(prefix = "app.mail")
record MailProperties(@NotBlank String host,
@Min(1) int port,
@DefaultValue("10s") Duration timeout,
List<String> recipients) {}
@SpringBootApplication
@ConfigurationPropertiesScan
class App { /* main */ }
@Service
class Mailer {
Mailer(MailProperties props) {
System.out.println(props.host() + ":" + props.port() + " " + props.timeout());
// dev profile -> localhost:587 PT5S
}
}Remember
@ConfigurationPropertiesbinds a prefix to a typed record or class@Validated+ constraints fail fast at startupapplication-{profile}.propertiesoverrides the defaults for that profile- Activate profiles with
SPRING_PROFILES_ACTIVE
Watch out for
- Creating a profile per feature flag, leading to combinatorial configurations; use plain properties for flags.