Properties, Profiles & Starters
The last foundations piece before you build anything real: how Spring Boot gets its configuration, how that configuration changes per environment, and what a "starter" dependency actually bundles.
Learning objectives
- Beginner: A single application.properties file for local development with a local database URL.
- Intermediate: Separate local/prod profile files, with secrets like DB passwords resolved from environment variables rather than committed to either file.
- Advanced: @Profile-annotated beans swapping entire implementations (e.g. a mock payment gateway in "test" vs. a real one in "prod"), combined with externalized secrets management for production credentials.
A starter is a curated dependency bundle — adding spring-boot-starter-web to your build pulls in Spring MVC, an embedded Tomcat, Jackson for JSON, and validation support, all in tested-compatible versions, instead of you individually selecting and version-matching each library yourself.
| Starter | Brings in |
|---|---|
| spring-boot-starter-web | Spring MVC, embedded Tomcat, Jackson — for building REST APIs (Module 06). |
| spring-boot-starter-data-jpa | Spring Data JPA, Hibernate, HikariCP connection pooling (Module 08). |
| spring-boot-starter-security | Spring Security core, auto-configured with a default login form (Module 12). |
| spring-boot-starter-validation | Bean Validation (Hibernate Validator) — @NotNull, @Size, etc. (Module 10). |
| spring-boot-starter-test | JUnit 5, Mockito, Spring Test — everything for writing tests (Module 11). |
# application.properties server.port=8081 spring.datasource.url=jdbc:postgresql://localhost:5432/bookdb spring.jpa.hibernate.ddl-auto=update
application.yml — same three settings, hierarchical
server: port: 8081 spring: datasource: url: jdbc:postgresql://localhost:5432/bookdb jpa: hibernate: ddl-auto: update
YAML's nesting removes the repeated spring.datasource. / spring.jpa.hibernate. prefixes, which is why larger projects tend to prefer it once the properties file grows past a handful of entries — purely a readability choice, both are parsed into the exact same configuration internally.
💻 Code example
# application.properties server.port=8081 spring.datasource.url=jdbc:postgresql://localhost:5432/bookdb spring.jpa.hibernate.ddl-auto=update
◆ The problem
A database password belongs in neither a committed application.properties file nor hardcoded Java — it needs to come from the actual deployment environment, different in local dev, CI, and production.
Spring Boot resolves configuration from multiple sources in a defined precedence order, letting an environment variable or command-line argument override a value set in application.properties without changing the file at all.
| Source |
|---|
| Command-line arguments (--server.port=9090) |
| Environment variables (SERVER_PORT=9090) |
| application-{profile}.properties (§05.4) |
| application.properties |
◆ Under the hood — relaxed binding
Spring Boot's "relaxed binding" is what lets an environment variable named SPRING_DATASOURCE_PASSWORD automatically satisfy the property spring.datasource.password — different naming conventions (dot-separated, underscore-separated, upper/lowercase) are all normalized to the same internal property key, so you don't need exact case-sensitive matches between shell environment variables and property file syntax.
# application-local.yml spring.datasource.url: jdbc:postgresql://localhost:5432/bookdb_local # application-prod.yml spring.datasource.url: ${DATABASE_URL}
activate a profile at startup
java -jar app.jar --spring.profiles.active=prod
A @Profile("prod") annotation on a bean or configuration class restricts that bean to only be created when the named profile is active — commonly used to swap an entire implementation (e.g. a real email service vs. a logging-only stub) per environment, not just a property value.
✓ Quick recap
What does a starter dependency actually give you beyond a single jar? A curated, version-compatible bundle of everything typically needed for one capability. Why does an environment variable like SPRING_DATASOURCE_PASSWORD satisfy spring.datasource.password? Relaxed binding normalizes different naming conventions to the same internal property key.
💻 Code example
# application-local.yml spring.datasource.url: jdbc:postgresql://localhost:5432/bookdb_local # application-prod.yml spring.datasource.url: ${DATABASE_URL}
Want a visual for this concept?
Generate a diagram tailored to “Properties, Profiles & Starters” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.
Sign in to generate a visual →