1. Introduction
The @Value annotation in Spring is a powerful way to inject properties from configuration files into classes. @Value works similarly to how it does in Java, but with some nuances due to Kotlin’s language features like null safety and default constructors.
In this tutorial, we’ll learn how to use @Value correctly.
2. Basic Usage of @Value
The @Value annotation allows us to inject values from our application’s properties directly into our Spring beans. We must escape the dollar sign in the property placeholder strings because Kotlin strings also use it for string interpolation.
Let’s write MyBean to demonstrate this:
@Component
class MyBean {
@Value("\${some.property}")
lateinit var propertyValue: String
}
This demonstrates field injection, populating propertyValue with the value of some.property from a Spring application properties file.
3. Constructor Injection
Kotlin favors immutability, and constructor injection is the preferred method when working with immutable properties:
@Component
class MyBean(@Value("\${some.property}") val propertyValue: String)
Specifically, propertyValue is a constructor parameter injected with the value of some.property. Here, propertyValue is immutable and ensures that the value remains unaltered after creation.
4. Working With Default Values
Spring allows us to specify default values for parameters, which we can combine with @Value to provide a default if a property isn’t set:
@Component
class MyBean(@Value("\${some.property:default}") val propertyValue: String)
In this setup, if some.property isn’t defined, propertyValue defaults to ‘default‘ If some.property isn’t defined and no default value is provided, the system throws an error because propertyValue must not be null. We can’t use Kotlin’s default arguments to provide a default value with @Value.
5. Null Values
Additionally, Kotlin’s null safety features require careful handling of possible null values injected by @Value. If there’s a chance that the property may not exist and we don’t provide a default, we should declare the property as nullable:
@Component
class MyBean(@Value("\${some.property:#{null}}") val propertyValue: String?)
This ensures that our Kotlin code remains null-safe. We use Spring Expression Language (SpEL) to define a null default. If we leave the String non-nullable and there is no value, we’ll get a runtime error:
Constructor threw exception; nested exception is java.lang.NullPointerException:
Parameter specified as non-null is null
6. Advanced Scenarios
The @Value annotation also supports more advanced SpEL uses, allowing for more complex expressions. This also includes the ability to read system properties:
@Component
class MyBean(@Value("#{systemProperties['some.property']}") val propertyValue: String)
Specifically, Spring injects propertyValue with the value of some.property from the system properties, demonstrating the flexibility of @Value and SpEL.
7. Conclusion
Using the @Value annotation in Spring allows for robust and flexible configuration management. Whether we’re using field injection or constructor injection, features like default parameters and null safety can help create a more concise and safe application. We should always ensure our property injections align with Kotlin’s type system to maintain null safety and immutability.
As always, the code used in this article is available over on GitHub.