Profiles let you register different beans and load different properties per environment — dev, test, prod — without changing code. Two mechanisms do the work: @Profile gates beans, and spring.profiles.active selects which profiles are live.
Gating beans with @Profile
@Profile on a @Component, @Configuration, or @Bean method makes it eligible only when the named profile is active:
@Configuration
public class MailConfig {
@Bean
@Profile("prod")
MailSender smtpSender() { return new SmtpMailSender(...); }
@Bean
@Profile("!prod") // any profile except prod
MailSender loggingSender() { return new LoggingMailSender(); }
}
The expression supports !, &, | and grouping: @Profile("prod & eu"). A bean with no @Profile is always registered.
Profile-specific properties
Files named application-<profile>.yml/.properties are loaded only when that profile is active, layered on top of the plain application.yml:
application.yml # common defaults
application-dev.yml # loaded when 'dev' is active
application-prod.yml # loaded when 'prod' is active
How to activate a profile
Many ways, highest precedence last (same hierarchy as any property):
# 1. In application.properties (the default fallback)
spring.profiles.active=dev
# 2. Command line — wins over the file
java -jar app.jar --spring.profiles.active=prod
# 3. JVM system property
java -Dspring.profiles.active=prod -jar app.jar
# 4. Environment variable (relaxed binding) — common in Docker/K8s
export SPRING_PROFILES_ACTIVE=prod
// 5. Programmatically, before refresh
new SpringApplicationBuilder(App.class)
.profiles("prod")
.run(args);
You can activate several at once: --spring.profiles.active=prod,eu,metrics.
Useful extras
spring.profiles.include/ profile groups (spring.profiles.group.prod=eu,metrics) activate bundles of profiles together.@ActiveProfiles("test")sets profiles in integration tests.- If no profile is set, the
defaultprofile applies — beans annotated@Profile("default")run only when nothing else is active.