Introduction:
The @PropertySource annotation in Spring provides a convenient and declarative mechanism for reading properties files. Properties files contain key-value pairs, e.g. app.log.level = DEBUG
. In this article, you will learn to read a value from the property file using @PropertySource
and access the specific values using @Value
annotation and Environment
field.
If you are new to Spring, make sure you understand the basics of Dependency Injection.
1. Use @PropertySource in conjunction with @Configuration
The @PropertySource annotation is used in conjunction with @Configuration annotation. It is also possible to define property source in an XML file. When we have a property file in the classpath or inside resources
, we can specify as below.
@Configuration
@PropertySource("classpath:app.properties")
@ComponentScan("com.jsbd.propertysource")
public class AppConfig {
//other stuffs
}
2. Access the value using @Value annotation
We will read the property file using @PropertySource
and access a value from this file using @Value("${}")
.
@Component
public class ConnectionManager {
@Value("${app.database.url}")
private String url;
@Value("${app.database.username}")
private String username;
}
The complete example is shown below.
package com.jsbd.propertysource;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:app.properties")
@ComponentScan("com.jsbd.propertysource")
public class AppConfig {
}
package com.jsbd.propertysource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.StringJoiner;
@Component
public class ConnectionManager {
@Value("${app.database.url}")
private String url;
@Value("${app.database.username}")
private String username;
@Value("${app.database.password}")
private String password;
@Value("${no.value}") //No value found
private String noValue;
@Override
public String toString() {
return new StringJoiner(", ", ConnectionManager.class.getSimpleName() + "[", "]")
.add("url='" + url + "'")
.add("username='" + username + "'")
.add("password='" + password + "'")
.add("noValue='" + noValue +"'")
.toString();
}
}
package com.jsbd.propertysource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestClass {
public static void main(String[] args) {
ApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(context.getBean(ConnectionManager.class));
}
}
app.database.url=http://random-url
app.database.password=abcd@123
app.database.username=root
Output:
ConnectionManager[url='http://random-url', username='root', password='abcd@123', noValue='${no.value}']
3. Use @PropertySource with Environment
The official spring doc recommends to use Environment
interface to access any property from a properties file.
@Component
public class AppLogger {
@Autowired //Use setter/constructor based injection
private Environment env;
public void printLogLevel() {
String logLevel = env.getProperty("app.log.level");
System.out.println(logLevel);
}
}
4. Specify multiple property sources using @PropertySources
It is possible to specify multiple property sources as well in Spring now.
@Configuration
@PropertySources({
@PropertySource("classpath:app.properties"),
@PropertySource("classpath:db.properties")
})
public class ApplicationConfig {
//...
}
If one or more specified PropertySource file is not found, spring will throw an Exception.
5. Ignore a Property file if not found
Occasionally, you may want the app to ignore the property source not found exception. Spring throws an exception when a specified file is not found.
Caused by: java.io.FileNotFoundException: class path resource [persistence.properties] cannot be opened because it does not exist
@Configuration
@PropertySource(value="classpath:persistence.properties", ignoreResourceNotFound=true)
public class AppConfig {
//...
}
6. Placeholder resolution
The Environment
is integrated throughout the Spring container, it allows the resolution of placeholders through it. Below is an example that shows the import of an xml config file and the name of this file is dynamically injected.
@Configuration
@ImportResource("classpth:${app.name}.xml")
public class AppConfig {
//extra stuff here
}
It does not matter who provides the app.name
value, this will work. Lets say instead of assigning this value from properties file, we assign it using the jvm parameter, this will work.
java -jar -Dapp.name="jpa-example" JpaApp.jarRemember:
- The
@PropertySource
annotation is repeatable, according to Java 8 conventions. - However, all such
@PropertySource
annotations need to be declared at the same level, either directly on the configuration class or as meta-annotations within the same custom annotation. - Mixing direct annotations and meta-annotations is not recommended since direct annotations effectively override meta-annotations.
Conclusion:
It is simple to use the @PropertySource annotation in Spring. Access the values using @Value("${property.name}")
and the Environment interface. Let me know your feedback on this article. You can find the complete example below.