What is the @PropertySource
annotation?
The @PropertySource
annotation is used to tell Spring to load a specific properties file from a location provided in the annotation. It is used in conjunction with @Configuration
at the class level. It allows you, as a developer, to externalize the configuration of your application.
Why use @PropertySource
?
- It allows you to load properties files from any location.
- In Java 8+, you can repeat this annotation many times, allowing you to load multiple configuration files.
- It supports the usage of placeholders using Spring Expression Language syntax.
- You can handle missing files by ignoring them if they are not found.
- Property override: if you have many properties with the same name, the last definition will override the first one.
How to use @PropertySource
The first example is the default way, by configuring with @Configuration
and pointing to a path:
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {
private static final Logger logger = getLogger(AppConfig.class);
@Value("${property.name}")
private String propertyName;
@PostConstruct
public void init() {
logger.info("Property loaded: property.name={}", propertyName);
}
// getters and setters
}
Here’s the configuration file:
property.name=property value
If you run the example above the init()
will show the value of the property in the console:
INFO 17840 --- [ main] org.spring.mastery.config.AppConfig : Property loaded: property.name=property value
You can define as many @PropertySource
annotations as you want:
@Configuration
@PropertySource("classpath:application.properties")
@PropertySource("classpath:another.properties")
public class AppConfig {
private static final Logger logger = getLogger(AppConfig.class);
@Value("${property.name}")
private String propertyName;
@Value("${another.property}")
private String anotherProperty;
@PostConstruct
public void init() {
logger.info("Property loaded: property.name={}", propertyName);
logger.info("Property loaded: property.name={}", anotherProperty);
}
// getters and setters
}
The console will have these lines:
INFO 28208 --- [ main] org.spring.mastery.config.AppConfig : Property loaded: property.name=property value
INFO 28208 --- [ main] org.spring.mastery.config.AppConfig : Property loaded: property.name=another valu
You can use @PropertySources
to group them if you want:
@Configuration
@PropertySources({
@PropertySource("classpath:application.properties"),
@PropertySource("classpath:another.properties")
})
public class AppConfig {
@Value("${property.name}")
private String propertyName;
@Value("${another.property}")
private String anotherProperty;
// getters and setters
}
It’ll work like the previous example:
INFO 28316 --- [ main] org.spring.mastery.config.AppConfig : Property loaded: property.name=property value
INFO 28316 --- [ main] org.spring.mastery.config.AppConfig : Property loaded: property.name=another value
You can use a placeholder using Spring Expression Language to make things more flexible by using one property to define a path location to another property file. You can use this in scenarios where you can add a .properties
file that will be placed outside your project (in this example is still in the class path, but you can put it where you want in the file system. This is useful in production systems where you want to hide the properties that will be used in the production server from the source code.
@Configuration
@PropertySource("classpath:${config.location}/external.properties")
public class AppConfig {
private static final Logger logger = getLogger(AppConfig.class);
@Value("${external.property.name}")
private String propertyName;
@PostConstruct
public void init() {
logger.info("Property loaded: property.name={}", propertyName);
}
// getters and setters
}
The application.properties
will look like this:
property.name=property value
config.location=external
And the external.properties
will look like this:
external.property.name=external value
PS: The external
name is optional; you can add the name you want.
You can also ignore the property loading if the file is not found:
@Configuration
@PropertySource(value = "classpath:optional.properties", ignoreResourceNotFound = true)
public class AppConfig {
private static final Logger logger = getLogger(AppConfig.class);
@Value("${optional.property:default}")
private String optionalProperty;
@PostConstruct
public void init() {
logger.info("Property loaded: property.name={}", optionalProperty);
}
// getters and setters
}
If the optional.properties
does not exist, the default value will be set:
INFO 8912 --- [ main] org.spring.mastery.config.AppConfig : Property loaded: property.name=default
If it exists, it will show the property value defined on the existing optional.properites
INFO 29992 --- [ main] org.spring.mastery.config.AppConfig : Property loaded: property.name=optional value
In this post, we learned different ways to use the @PropertySource
in your project. Have you seen another way to use it? Did this annotation help you solve a problem in your project?
If you like this topic, make sure to follow me. In the following days, I’ll be explaining more about Spring annotations! Stay tuned!