Externalize settings instead of hard-coding them — properties and YAML, @Value, type-safe @ConfigurationProperties, per-environment profiles, and secrets from the environment.
Why: configuration lives outside your code so the same build runs in dev and production with different settings. Note: application.properties and application.yml do the same job — YAML nests cleanly for grouped settings. Pick one per project.
# application.properties
server.port=8080
app.feature.signups-open=true
spring.datasource.url=jdbc:postgresql://localhost/bookstore# application.yml — the same settings, nested
server:
port: 8080
app:
feature:
signups-open: true
spring:
datasource:
url: jdbc:postgresql://localhost/bookstoreWhen @Value: you need a single setting in a bean. Note: the ${...} placeholder reads a property; add a default after a colon so the app still starts if it is missing. It's quick, but for a group of related settings prefer @ConfigurationProperties.
@Service
public class SignupService {
@Value("${app.feature.signups-open:false}") // default = false
private boolean signupsOpen;
public boolean canSignup() {
return signupsOpen;
}
}Why: binds a whole group of properties to a typed object — no scattered ${...} strings, with IDE completion and validation. When: any time you have more than one or two related settings (an "app.*" block). Note: enable scanning with @ConfigurationPropertiesScan on the main class.
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "app")
public record AppProperties(Feature feature) {
public record Feature(boolean signupsOpen) {}
}
// binds:
// app.feature.signups-open=true
// inject AppProperties anywhere and read appProperties.feature().signupsOpen()Why: a profile is a named set of overrides for one environment. Note: application-dev.yml and application-prod.yml layer on top of the base file; activate one with spring.profiles.active. @Profile puts a whole bean behind a profile (e.g. seed data only in dev).
# application-prod.yml — only used when the "prod" profile is active
server:
port: 80
logging:
level:
root: WARN# choose the profile at startup
java -jar bookstore.jar --spring.profiles.active=prodWhy: passwords and API keys must never be committed. Note: reference an environment variable from a property with ${ENV_VAR} — Spring reads OS environment variables automatically, so production injects the real value while your file stays safe to commit.
# application.properties — no real secrets here
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
jwt.secret=${JWT_SECRET}