Introduction
As we already know, Spring provides many ways to achieve the same thing, and one of them is how to retrieve the values registered in your configuration file.
If you're new to Spring, you might come across code that uses the @Value annotation to retrieve values from your application.properties or application.yml file. If you're using this approach, know that it's not wrong; however, you might be introducing unnecessary complexity into your application.
The Problem with @Value
The main issue with using @Value arises when we deal with values that contain other values. Does that make sense? No? Let's look at an example:
Suppose you have the following configuration file:
mail.user=dev@locahost
mail.password=123
mail.headers.x-from=Ekerdev
mail.headers.x-custom=custom
You would need to do it like this:
@Service
public class CustomService {
@Value("mail.user")
private String user;
@Value("mail.password")
private String password;
@Value("mail.headers.x-from")
private String xFrom;
@Value("mail.headers.x-custom")
private String xCustom;
}
So far, no problem. But now imagine a scenario where your application needs to use these same values in multiple places in the code. Think of how much duplicated code we’d end up with, right?
The Solution
The best solution, then, is to use the @ConfigurationProperties annotation. This makes it easier for our application to inject variables into a class, and we can use it just like any other dependency in Spring, injecting it as shown in the example below:
Alternative 1 using Spring 3.x:
@Configuration
@ConfigurationProperties("mail")
public record MailProperties(
String user,
String password,
Map<String, String> headers
) {}
Alternative 2 using Spring 3.x:
@Configuration
@ConfigurationProperties("mail.headers")
public record MailHeadersProperties(
String xFrom,
String xCustom,
) {}
@Configuration
@ConfigurationProperties("mail")
public record MailProperties(
String user,
String password,
MailHeadersProperties headers,
) {}
Alternative 1 using Spring 2.x:
@Data
@AllArgsConstructor
@ConfigurationPropertiesScan
@ConfigurationProperties("mail")
public class MailProperties {
private String user;
private String password;
private Map<String, String> headers;
}
@SpringBootApplication
@ConfigurationPropertiesScan("your.package.mailproperties")
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
And your service use properties like this:
@Service
@RequiredArgsConstructor
public class CustomService {
private final MailProperties mailProperties;
}
The Advantage
The major advantage of using @ConfigurationProperties is that we don't have to hunt for @Value annotations in our code, which makes the code much more readable.
Top comments (1)
Very useful. Thanks for sharing