All articles
Spring BootSpring CoreExam Tips

Spring Profiles & External Properties Exam Guide (2V0-72.22)

September 2, 202621 min read

What External Properties and Profiles Mean in Spring

External properties are configuration values that live outside your compiled code — in application.properties, environment variables, command-line arguments, JNDI, or a file on the production server. Spring reads them all through one abstraction, the Environment, so your code never needs to know where a value came from.

Profiles are named groups that decide which beans get created and which property files get loaded. A profile called dev might wire an in-memory database, while prod wires a connection pool against a real one — same code, different configuration.

On the 2V0-72.22 exam, this is objective 1.3 "Properties and Profiles" inside the Spring Core section (28% of questions), and it appears again in the Spring Boot section (28%) as "describe options for defining and loading properties". Expect questions on which property source wins when two sources define the same key, the difference between @Value and @ConfigurationProperties, how @Profile expressions evaluate, and what a profile-specific file actually does.

Version note: The exam targets Spring Framework 5.3 / Spring Boot 2.5–2.7. Everything below applies to Spring Boot 3.x as well, and every place where behaviour changed at Boot 2.4 or Boot 3.0 is called out explicitly — Boot 2.4 rewrote config file processing, and a lot of study material still describes the old rules.


The Short Answer

If you only memorise five things from this guide, memorise these:

  1. Later sources override earlier ones, and command-line arguments beat everything in a normal application run. --server.port=9090 wins over a system property, an environment variable, and application.properties.
  2. Java system properties beat OS environment variables. Most candidates get this backwards.
  3. @PropertySource sits below application.properties, so it can never override it.
  4. Profile-specific files are layered on top of the plain file, not swapped for it. application-dev.properties overrides application.properties key by key; keys it does not mention still come from the plain file.
  5. @Value injects one value and supports SpEL; @ConfigurationProperties binds a whole group and supports relaxed binding and validation. Neither does the other's job.

Where Properties Come From: The Precedence Order

Spring Boot collects property sources into an ordered list. When you ask for server.port, the first source that has it wins. The official reference lists these lowest-priority first; the ladder below is inverted, because the question you actually ask is "what wins?"

Highest priority — this winsSpring Boot 2.4+
  1. 1Devtools global settingsdev only~/.config/spring-boot — development machines only
  2. 2Test annotationstests only@TestPropertySource, @DynamicPropertySource, @SpringBootTest(properties)
  3. 3Command-line arguments--server.port=9090
  4. 4SPRING_APPLICATION_JSONInline JSON in an environment variable or system property
  5. 5Servlet init parametersServletConfig first, then ServletContext
  6. 6JNDI attributesjava:comp/env
  7. 7Java system properties-Dserver.port=9090
  8. 8OS environment variablesSERVER_PORT=9090
  9. 9random.* valuesRandomValuePropertySource
  10. 10Config data filesgroupapplication.properties / .yml — see the nested order below
  11. 11@PropertySourceOn a @Configuration class — below application.properties, not above it
  12. 12Default propertiesSpringApplication.setDefaultProperties(…)
Lowest priority — overridden by everything above
Inside rung 10 — config data files
  1. 1.Profile-specific, outside the jar — application-{profile}.properties
  2. 2.Plain, outside the jar — application.properties
  3. 3.Profile-specific, inside the jar
  4. 4.Plain, inside the jar

External beats packaged, and profile-specific beats plain — but a packaged profile-specific file still loses to a plain file outside the jar.

The same order as a table, with the example you are most likely to see in a question:

#Property sourceExample
1Devtools global settings~/.config/spring-boot (development machines only)
2Test annotations@TestPropertySource, @DynamicPropertySource, @SpringBootTest(properties = …)
3Command-line argumentsjava -jar app.jar --server.port=9090
4SPRING_APPLICATION_JSONSPRING_APPLICATION_JSON='{"server":{"port":9090}}'
5Servlet init parametersServletConfig first, then ServletContext
6JNDI attributesjava:comp/env
7Java system propertiesjava -Dserver.port=9090 -jar app.jar
8OS environment variablesSERVER_PORT=9090
9RandomValuePropertySourceapp.id=${random.uuid}
10Config data filesapplication.properties / application.yml
11@PropertySource@PropertySource("classpath:extra.properties")
12Default propertiesSpringApplication.setDefaultProperties(…)

Exam tip: System properties (-D) beat environment variables, not the other way round. Both beat anything in application.properties. This single ordering fact accounts for a large share of the property questions candidates get wrong.

Exam tip: @PropertySource is at position 11 — below config data files. A key defined in both application.properties and a @PropertySource file resolves to the application.properties value. If a question offers "the @PropertySource value overrides application.properties", it is wrong.

The Four Config Data Locations

Rung 10 is itself an ordered group. Within config data files, later wins:

PriorityLocation
HighestProfile-specific file outside the jar — ./config/application-prod.properties
Plain file outside the jar — ./application.properties
Profile-specific file inside the jar
LowestPlain file inside the jar

Exam tip: External beats packaged, and profile-specific beats plain — but the grouping matters: a packaged profile-specific file still loses to a plain file outside the jar. Externalising a file promotes it above everything bundled in the artifact.

Spring Boot searches a fixed list of default locations for config data, and later locations override earlier ones:

classpath:/
classpath:/config/
file:./
file:./config/
file:./config/*/

The last entry means the immediate subdirectories of config/, which is how mounted configuration volumes are picked up without naming each one.

You can change what it looks for with spring.config.name (default application), or where it looks with spring.config.location (replaces the defaults) and spring.config.additional-location (adds to them).

java -jar app.jar --spring.config.name=myapp
java -jar app.jar --spring.config.location=file:/etc/myapp/
java -jar app.jar --spring.config.additional-location=file:/etc/myapp/

Exam tip: spring.config.location replaces the default search locations; spring.config.additional-location adds to them. Swapping the two is a common distractor.


application.properties vs application.yml

Spring Boot accepts both formats, and they are equivalent in capability. The .properties format is flat key/value; YAML is hierarchical and better for deeply nested configuration.

spring.datasource.url=jdbc:postgresql://localhost/orders
spring.datasource.username=app
app.retry.max-attempts=3
app.allowed-origins=https://a.example,https://b.example
spring:
  datasource:
    url: "jdbc:postgresql://localhost/orders"
    username: "app"
app:
  retry:
    max-attempts: 3
  allowed-origins:
    - "https://a.example"
    - "https://b.example"

Exam tip: If application.properties and application.yml exist in the same location, .properties takes precedence. The recommendation is to pick one format per application and stay with it.

Both formats support multi-document files, where each document can be activated conditionally. YAML separates documents with ---; the properties format uses a comment-style separator #---.

app.mode: "shared"
---
spring:
  config:
    activate:
      on-profile: "prod"
app.mode: "strict"
app.mode=shared
#---
spring.config.activate.on-profile=prod
app.mode=strict

Exam tip: YAML files cannot be loaded through @PropertySource or @TestPropertySource. Those annotations understand the .properties format only. If you need YAML in a test, use @ActiveProfiles with a profile-specific YAML file, or register the source yourself.

YAML also binds lists positionally, which matters when an environment variable has to override one:

app:
  servers:
    - "one.example"
    - "two.example"

The equivalent flat keys are app.servers[0] and app.servers[1].


Reading Properties: @Value, Environment and SpEL

Property Placeholders with @Value

@Value injects a single resolved value into a field, constructor parameter, or method parameter.

@Service
public class ReportService {
 
    private final int timeoutMs;
 
    public ReportService(@Value("${app.timeout-ms:5000}") int timeoutMs) {
        this.timeoutMs = timeoutMs;
    }
}

The :5000 after the key is a default value, used when the property is absent.

Exam tip: Without a default, an unresolvable placeholder fails the context at startup, not at first use. @Value("${app.missing}") throws IllegalArgumentException: Could not resolve placeholder 'app.missing'. That fail-fast behaviour is deliberate and is frequently tested.

${...} Is Not #{...}

This is the single most common syntax trap in the objective:

SyntaxNameResolves to
${...}Property placeholderA value from the Environment
#{...}SpEL expressionThe result of evaluating an expression
@Value("${app.name}")            // property placeholder
private String name;
 
@Value("#{systemProperties['user.region']}")   // SpEL
private String region;
 
@Value("#{T(java.lang.Math).random() * 100}")  // SpEL: static method call
private double sample;
 
@Value("#{'${app.allowed-origins}'.split(',')}")  // both: placeholder inside SpEL
private List<String> origins;

Exam tip: #{...} is evaluated by the Spring Expression Language, ${...} by the property placeholder resolver. A placeholder can be nested inside a SpEL expression (as in the last example), because the placeholder is resolved first, but the reverse is not true.

Injecting the Environment Directly

When you need to read a property programmatically, inject Environment:

@Service
public class FeatureService {
 
    private final Environment env;
 
    public FeatureService(Environment env) {
        this.env = env;
    }
 
    public boolean isEnabled() {
        return env.getProperty("app.feature.enabled", Boolean.class, false);
    }
 
    public String requiredRegion() {
        return env.getRequiredProperty("app.region"); // throws if absent
    }
}

Environment also answers profile questions: getActiveProfiles(), getDefaultProfiles(), and acceptsProfiles(Profiles.of("dev | test")).

Exam tip: In a plain Spring application (no Boot), ${...} placeholders in @Value only work if a static PropertySourcesPlaceholderConfigurer bean is registered. Spring Boot registers it for you, which is why the annotation "just works" there. The bean must be static so it is instantiated early, before other beans are configured.


@PropertySource: Loading Extra Files

@PropertySource adds a .properties file to the Environment from a @Configuration class. It is core Spring, not Boot, and it is what the exam expects you to reach for when a question is not Boot-specific.

@Configuration
@PropertySource("classpath:integration.properties")
@PropertySource(value = "file:/etc/app/override.properties", ignoreResourceNotFound = true)
public class IntegrationConfig {
}

Key behaviours:

BehaviourDetail
Formats.properties and XML properties files — not YAML
Missing fileFails the context unless ignoreResourceNotFound = true
Duplicate keys across several @PropertySourceThe last annotation processed wins
Precedence vs application.propertiesLower — cannot override config data
RepeatableYes; @PropertySources is the container annotation

Resource prefixes work as everywhere else in Spring: classpath:, file:, and http:.


@ConfigurationProperties: Type-Safe Binding

@Value is fine for one or two values. Once a component needs a group of related settings, @ConfigurationProperties binds them to a typed object in one step.

@ConfigurationProperties(prefix = "app.retry")
public class RetryProperties {
 
    private int maxAttempts = 3;
    private Duration backoff = Duration.ofSeconds(1);
 
    public int getMaxAttempts() { return maxAttempts; }
    public void setMaxAttempts(int maxAttempts) { this.maxAttempts = maxAttempts; }
 
    public Duration getBackoff() { return backoff; }
    public void setBackoff(Duration backoff) { this.backoff = backoff; }
}
app.retry.max-attempts=5
app.retry.backoff=2s

Note that Duration binds from 2s, 500ms or PT2S without any custom conversion — Spring Boot ships converters for Duration, Period, DataSize and enums.

Three Ways to Register It

RegistrationHowWhen to use
@EnableConfigurationProperties(RetryProperties.class)On a @Configuration classExplicit, and the only option for constructor-bound types you do not scan
@ConfigurationPropertiesScanOn the application classScans a package for @ConfigurationProperties types
@Component on the properties classStereotype + component scanningSimple setter-bound classes only

Exam tip: A @ConfigurationProperties class is not picked up automatically just because it carries the annotation. It must be registered through one of the three routes above. A question showing only the annotated class and asking "why is nothing bound?" is testing exactly this.

Relaxed Binding

@ConfigurationProperties matches property names loosely, so the same Java field binds from several spellings:

FormExample for maxAttemptsWhere it works
Kebab-caseapp.retry.max-attemptsEverywhere — the recommended canonical form
Camel-caseapp.retry.maxAttemptsProperties, YAML, system properties
Snake-caseapp.retry.max_attemptsProperties, YAML, system properties
Upper-caseAPP_RETRY_MAXATTEMPTSEnvironment variables

Exam tip: Relaxed binding is a feature of @ConfigurationProperties only. @Value("${app.retry.max-attempts}") requires the name to match a source exactly — set APP_RETRY_MAXATTEMPTS as an environment variable and the @ConfigurationProperties binding works while the @Value may not. Always write placeholders in the canonical kebab-case form.

Constructor Binding and Immutability

Binding through a constructor produces an immutable configuration object, and a Java record is the shortest way to express it:

@ConfigurationProperties(prefix = "app.retry")
public record RetryProperties(int maxAttempts, @DefaultValue("1s") Duration backoff) {
}

Version note: In Boot 2.2–2.6, constructor binding required @ConstructorBinding on the type. From Boot 3.0, the annotation is allowed on constructors only, and it is needed just to disambiguate when a class has more than one constructor — a single parameterized constructor is used for binding automatically.

Exam tip: A constructor-bound @ConfigurationProperties class cannot be registered with @Component, @Bean or @Import. Use @EnableConfigurationProperties or @ConfigurationPropertiesScan. Defaults for constructor-bound properties come from @DefaultValue, not from field initialisers.

Validation

Add @Validated and standard JSR-303 constraints, and a bad configuration fails the context at startup instead of surfacing as a NullPointerException an hour into production.

@Validated
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
 
    @NotBlank
    private String host;
 
    @Min(1) @Max(65535)
    private int port = 25;
 
    @Valid
    private final Retry retry = new Retry();
 
    // getters and setters omitted
}

Exam tip: Nested objects are not validated unless the field carries @Valid. @Validated on the outer class alone only validates the outer class's own constraints.

You can also apply @ConfigurationProperties to a @Bean method, which is how you bind configuration into a third-party class you cannot annotate:

@Bean
@ConfigurationProperties(prefix = "app.datasource")
public HikariDataSource dataSource() {
    return new HikariDataSource();
}

That pattern is a useful contrast with @Component vs @Bean: the annotation goes wherever the object is created. Every bound @ConfigurationProperties object is also listed by the Actuator /configprops endpoint — see the Actuator exam guide for how that endpoint and /env sanitize sensitive values.


@Value vs @ConfigurationProperties

@ValueOne value
  • Injects one property at a time
  • Supports SpEL: #{...}
  • Inline default: ${key:fallback}
  • Relaxed binding
  • JSR-303 validation
  • Lists, maps and nested objects
@ConfigurationPropertiesA group
  • Binds a whole group to a typed object
  • Relaxed binding: kebab, camel, UPPER_SNAKE
  • Lists, maps and nested objects
  • JSR-303 validation via @Validated
  • Constructor binding gives immutable config
  • Supports SpEL
Feature@Value@ConfigurationProperties
BindsOne value at a timeA whole group, by prefix
Relaxed bindingNo — exact nameYes
SpEL (#{...})YesNo
Lists, maps, nested objectsLimitedYes
JSR-303 validationNoYes, with @Validated
Immutabilityfinal field via constructorConstructor binding / records
Missing propertyStartup failure unless a default is givenLeft at its default value
IDE metadata & completionNoYes

Rule of thumb: reach for @Value when you need one value or an expression, and @ConfigurationProperties when a component owns a coherent block of settings. The Spring team's own auto-configuration classes use @ConfigurationProperties almost exclusively — see how auto-configuration works for how @ConditionalOnProperty then switches beans on and off based on those same values.


Spring Profiles: @Profile and Profile Expressions

@Profile makes a bean definition conditional on the active profiles. It can go on a @Component, on a @Configuration class, or on an individual @Bean method.

@Configuration
@Profile("dev")
public class DevDataSourceConfig {
 
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
    }
}
 
@Configuration
@Profile("prod")
public class ProdDataSourceConfig {
 
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

Exam tip: @Profile on a @Configuration class disables every @Bean method inside it when the profile is not active. Put it on the class when the whole block belongs to one environment, and on individual methods when only some beans do.

Profile Expressions

Since Spring 5.1, @Profile accepts a boolean expression:

OperatorMeaningExample
!NOT@Profile("!prod")
&AND@Profile("prod & cloud")
|OR@Profile("prod | staging")

Exam tip: You cannot mix & and | without parentheses. @Profile("a & b | c") is invalid and throws at startup; write @Profile("(a & b) | c") or @Profile("a & (b | c)").

Listing several profiles in the array form is an OR: @Profile({"dev", "test"}) activates the bean when either is active.

The default Profile

When no profile is explicitly activated, Spring uses a profile named default.

@Bean
@Profile("default")
public DataSource fallbackDataSource() {
    return new EmbeddedDatabaseBuilder().build();
}

Exam tip: A @Profile("default") bean is created only while no profile is explicitly active. Start the application with --spring.profiles.active=dev and that bean disappears — even though dev says nothing about it. Environment.getActiveProfiles() returns an empty array in that situation, while getDefaultProfiles() returns ["default"]. Rename the default with spring.profiles.default.

Profile names are validated: letters, digits and the characters -, _, ., + and @ are allowed, and a name must start and end with a letter or digit. Set spring.profiles.validate=false to opt out.


Activating Profiles

spring.profiles.active is an ordinary property, so it obeys the precedence ladder above. That is why a command-line argument beats whatever the packaged application.properties says.

MechanismExampleNotes
application.propertiesspring.profiles.active=devLowest of these; a baseline, not a lock
Environment variableSPRING_PROFILES_ACTIVE=prodOverrides the file
System property-Dspring.profiles.active=prodOverrides the environment variable
Command-line argument--spring.profiles.active=prodOverrides the system property
Programmaticapplication.setAdditionalProfiles("dev")Adds profiles, does not replace
Tests@ActiveProfiles("test")Applies to the test context only
public static void main(String[] args) {
    SpringApplication application = new SpringApplication(MyApplication.class);
    application.setAdditionalProfiles("dev", "hsqldb");
    application.run(args);
}

Including and Grouping Profiles

spring.profiles.include adds profiles unconditionally, on top of whatever is active. Included profiles are added before the ones from spring.profiles.active.

spring.profiles.include[0]=common
spring.profiles.include[1]=local

spring.profiles.group (Boot 2.4+) defines an alias that expands into several profiles:

spring.profiles.group.production[0]=proddb
spring.profiles.group.production[1]=prodmq

Running with --spring.profiles.active=production now activates production, proddb and prodmq together.

Exam tip: spring.profiles.active, spring.profiles.default, spring.profiles.include and spring.profiles.group cannot appear in a profile-specific document — not in application-dev.properties, and not in a document guarded by spring.config.activate.on-profile. Boot fails with InvalidConfigDataPropertyException. Letting a profile activate another profile was possible before Boot 2.4 and is exactly what the rewrite removed.


Profile-Specific Configuration Files

Name a file application-{profile}.properties (or .yml) and Spring Boot loads it in addition to application.properties whenever that profile is active.

# application.properties — shared baseline
app.name=Orders
app.retry.max-attempts=3
logging.level.root=INFO
 
# application-prod.properties — only the differences
app.retry.max-attempts=10
logging.level.root=WARN

With prod active, app.name is still Orders: the profile-specific file overrides key by key and inherits the rest.

Exam tip: A profile-specific file does not replace the plain file. Candidates who expect application-prod.properties to be the whole configuration get the "what is the value of app.name?" question wrong.

When several profiles are active, a last-wins strategy applies. With --spring.profiles.active=prod,live, values in application-live.properties override those in application-prod.properties.

spring.config.activate.on-profile

Instead of separate files, a single multi-document file can hold conditional sections:

app:
  mode: "shared"
---
spring:
  config:
    activate:
      on-profile: "prod | staging"
app:
  mode: "strict"

Version note: This property replaced spring.profiles in Spring Boot 2.4. Study material that shows spring.profiles: prod inside a YAML document predates the config data rewrite. spring.config.activate.on-profile accepts the same expression syntax as @Profile, including !, & and |.

A document can also be activated by cloud platform with spring.config.activate.on-cloud-platform=kubernetes.

Importing Extra Config

spring.config.import (Boot 2.4+) pulls in additional configuration, and the imported document is treated as if it sat immediately below the one that declared the import:

spring.config.import=optional:file:./dev.properties
spring.config.import=optional:configtree:/etc/config/

The optional: prefix means "do not fail if it is missing". Without it, a missing import fails startup — which is usually what you want for a mounted secret.


Profiles and Properties in Tests

Test annotations sit near the very top of the precedence ladder, which is what makes them able to override anything the application ships with.

@SpringBootTest(properties = "app.retry.max-attempts=1")
@ActiveProfiles("test")
class OrderServiceTest {
    // ...
}
AnnotationPurpose
@ActiveProfiles("test")Activates profiles for the test context
@SpringBootTest(properties = …)Inline property overrides for that test
@TestPropertySource(properties = …)Inline overrides, and locations for .properties files
@DynamicPropertySourceValues known only at runtime, e.g. a Testcontainers port

Exam tip: @TestPropertySource outranks @SpringBootTest(properties = …), and both outrank command-line arguments and everything below. Like @PropertySource, @TestPropertySource cannot read YAML.

Each distinct combination of profiles and properties produces a separate cached application context, which is the usual reason a test suite gets slow. The Spring Boot testing exam guide covers context caching and test slices in detail.


Common Exam Traps

1. System properties beat environment variables. -Dserver.port=9090 wins over SERVER_PORT=8081. Both win over application.properties.

2. @PropertySource cannot override application.properties. It sits one rung below config data. Distractors that claim otherwise are wrong.

3. @PropertySource and @TestPropertySource cannot load YAML. Only .properties (and XML properties) files.

4. ${...} and #{...} are different resolvers. ${} is a property placeholder; #{} is SpEL. A placeholder may be nested inside SpEL, never the reverse.

5. @Value has no relaxed binding. APP_RETRY_MAXATTEMPTS binds into @ConfigurationProperties but may not resolve a @Value placeholder. Write placeholders in canonical kebab-case.

6. A profile-specific file is layered, not swapped. application-prod.properties overrides individual keys; everything else still comes from application.properties.

7. Profile-activating properties are banned inside profile-specific documents. spring.profiles.active, .default, .include and .group there cause InvalidConfigDataPropertyException.

8. @Profile("default") beans vanish once any profile is active. Activating dev removes them, even though dev never mentions them.

9. Mixing & and | without parentheses is invalid. "a & b | c" throws; write "(a & b) | c".

10. .properties beats .yml in the same location. Keeping both files around is a real-world footgun and a favourite exam distractor.

11. A @ConfigurationProperties class must be registered. @EnableConfigurationProperties, @ConfigurationPropertiesScan, or @Component — the annotation alone binds nothing.

12. An unresolvable @Value placeholder fails at startup. Not at first access. Supply a default with ${key:fallback} if the property is genuinely optional.


Summary

ConceptKey point
PrecedenceLater sources win; command-line arguments beat everything in a normal run
System vs envJava system properties (-D) outrank OS environment variables
Config data orderExternal beats packaged; profile-specific beats plain
.properties vs .yml.properties wins in the same location
${} vs #{}Property placeholder vs SpEL expression
@ValueOne value, SpEL, inline defaults, no relaxed binding
@ConfigurationPropertiesGroup binding, relaxed binding, collections, @Validated
Registration@EnableConfigurationProperties / @ConfigurationPropertiesScan / @Component
@PropertySource.properties only, below config data, ignoreResourceNotFound
@ProfileConditional beans; supports !, &, `
default profileActive only when no profile is explicitly active
Activationspring.profiles.active is a normal property, so the ladder applies
include / groupAdditive activation; both banned in profile-specific documents
Profile filesapplication-{profile} layers over application; last profile wins
Boot 2.4spring.profiles became spring.config.activate.on-profile

Properties and profiles look like configuration trivia until you see how many exam questions reduce to one ordering fact. If you can rebuild the precedence ladder from memory and explain what a profile-specific file does to the plain one, you have most of objective 1.3.


Frequently Asked Questions

What is the property precedence order in Spring Boot?

From highest to lowest: devtools global settings, test annotations (@TestPropertySource, @DynamicPropertySource, @SpringBootTest(properties)), command-line arguments, SPRING_APPLICATION_JSON, servlet init parameters, JNDI attributes, Java system properties, OS environment variables, random.* values, config data files (application.properties / .yml), @PropertySource, and finally default properties set through SpringApplication.setDefaultProperties. In a normal application run — no tests, no devtools — command-line arguments win over everything.

Do environment variables override application.properties?

Yes. OS environment variables sit above config data files, so SERVER_PORT=9090 overrides server.port=8080 in application.properties. However, Java system properties override environment variables, and command-line arguments override both. Environment variables use relaxed binding, so APP_RETRY_MAXATTEMPTS binds to app.retry.max-attempts in a @ConfigurationProperties class.

What is the difference between @Value and @ConfigurationProperties?

@Value injects a single property into a field or parameter and supports SpEL expressions with #{...} and inline defaults with ${key:fallback}, but it has no relaxed binding and no validation. @ConfigurationProperties binds a whole group of properties by prefix into a typed object, supports relaxed binding, collections, maps, nested objects, JSR-303 validation via @Validated, and constructor binding for immutability — but it does not support SpEL. Use @Value for one-off values and @ConfigurationProperties when a component owns a block of settings.

How do I activate a Spring profile?

Set the spring.profiles.active property. Because it is an ordinary property, every activation route follows the normal precedence order: application.properties is the weakest, then the SPRING_PROFILES_ACTIVE environment variable, then -Dspring.profiles.active, then --spring.profiles.active=prod on the command line. In code, SpringApplication.setAdditionalProfiles(…) adds profiles rather than replacing them, and in tests @ActiveProfiles applies to that test context only.

Does application-prod.properties replace application.properties?

No. Profile-specific files are loaded in addition to the plain file and override it key by key. Keys that the profile-specific file does not mention keep the values from application.properties. When several profiles are active a last-wins strategy applies, so with spring.profiles.active=prod,live the values in application-live.properties beat those in application-prod.properties.

Can @PropertySource load a YAML file?

No. @PropertySource and @TestPropertySource understand the .properties format (and XML properties files) only — YAML files cannot be loaded through either annotation. Use profile-specific YAML files, spring.config.import, or register a YamlPropertySourceLoader yourself. Remember also that @PropertySource ranks below application.properties, so it cannot override config data.

Practice exam-style questions on properties and profiles — free interactive drilling with detailed explanations

Spring Boot auto-configuration explained — how @ConditionalOnProperty turns these values into bean decisions

Spring Boot testing exam guide@ActiveProfiles, test property sources, and context caching

How to prepare for the Spring Professional exam — complete 8-week study plan

Get Full Access — 2600+ Questions — full practice exam bank with detailed explanations

Practice This Topic

Reinforce what you've learned with free practice questions and detailed explanations.