12 Ways to Use the @Value Annotation in Spring for Flexible and Maintainable Applications
Tags: java, spring, tutorial, programming
Published: 2024-06-06 02:17:28


You may already be familiar with @Value annotation from Spring. This annotation allows you to inject some properties into your beans. 

But there’s a lot of ways you could do that. And maybe you are not familiar with all of them.

This article will show you many ways to work with @Value and some new ways you can apply to your projects.

Let’s explore our options!

### 1. Basic property injection

This is the most used option in Spring projects. It’s the common way you can control feature flags, API keys, database connection details, etc.

Example:

```java
@Value("${feature.enableDarkMode}")
private boolean isDarkModeEnabled;
```

Properties:

```java
feature.enableDarkMode=true
```

### 2. Hardcoded Values:

This way set the value as a constant in your code, this way you cannot change it externally.

```java
@Value("localhost")
private String defaultServerAddress;
```

### 3. Constructor Injection

Here is to create immutable beans that need their dependencies and values upfront.

Example:

```java
public TestBean(@Value("${mail.smtp.server}") String smtpServer) {
    this.smtpServer = smtpServer;
}

```

Properties:

```java
mail.smtp.server=smtp.example.com
```

### 4. SetUp Default Values:

You can provide default values when injecting your properties to avoid application crashes. If you do not have the property set, it will automatically pick the default value.

Example:

```java
@Value("${app.cache.ttl:60}")  // Default TTL of 60 seconds if not configured
private int cacheTimeToLive;
```

### 5. Inject Using Set Method (Less common)

This is an option in some legacy code bases, where construction is not possible, this way of injection becomes an option.

Example:

```java
@Value("${log.level}")
public void setLogLevel(String logLevel) {
    this.logLevel = logLevel;
}
```

Properties:

```java
log.level=INFO
```

### 6. Injecting an Array of values:

You can set an array of values, using comma-separated values, Spring will automatically split values and put them in the array positions. You can use this to set an array of allowed origins configured by properties. 

Example:

```java
@Value("${cors.allowedOrigins}")
private String[] allowedOrigins;
```

Properties:

```java
cors.allowedOrigins=https://example1.com,https://example2.com
```

### 7. Injecting a List of Values:

If you want more flexibility in your Java code, injecting a collection of values you can use SpEL to split values to create the list.

Example:

```java
@Value("#{'${notification.channels}'.split(',')}")
private List<String> notificationChannels;
```

Properties:

```java
notification.channels=EMAIL,SMS,PUSH
```

### 8. Inject Maps

You can inject in a Java map a group of configurations that uses key-value pattern.

Example:

```java
@Value("#{${http.client.config}}")
private Map<String, Integer> httpClientConfig;

```

Properties:

```java
http.client.config={timeout: 500, maxConnections: 100}
```

### 9. Inject a Single Value From a Map

In the same way, you can inject an entire map of values, you can use SpEL to inject a single value using its key.

Example:

```java
@Value("#{${http.client.config}['timeout']}")
private int timeout;
```

Properties:

```java
http.client.config={timeout: 500, maxConnections: 100}
```

### 10. Access System Properties

This method will allow you to get the system properties from the Java properties, also it gets all the properties that you set when running the application with the -D parameter.

Example:

```java
@Value("#{systemProperties['java.home']}")
private String javaHome;
```

In this example, the `java.home` is already passed automatically to the process. But if you want to access some custom property you can do this:

```java
@Value("#{systemProperties['custom.property']}")
private String javaHome;
```

Running the project with custom property:

```java
java -Dcustom.property="value" -jar app.jar
```

### 11. Get Environment Variables:

You can read an environment variable from your system (if the application has access to the variable).

Example:

```java
@Value("#{environment['MY_ENV_VAR']}")
private String myEnvVar;
```

### 12. Use SpEL and Create Dynamic Properties

One common problem developers have is that the team members can be working on different OS, so you can create a dynamic property based on the system to make things more flexible.

Example:

```java
@Value("#{systemProperties['os.name'].toLowerCase().contains('windows') ? 'C:\\' : '/'}")
private String rootDirectory;
```

This will get the [os.name](http://os.name) from the system and decide what is the root directory to inject the value.

That’s it! Now you have a whole set of new ways to configure your Spring applications with @Value!

That will give you more flexibility and options. It will offer a solution that fills your needs. By understanding how it works you can write more maintainable Spring applications.

Test out new ways of Injecting properties into your project!

If you like this topic, make sure to follow me, in the following days, I’ll be explaining more about the Spring annotations!

Stay tuned!

### References

1. [Baeldung: Spring @Value Annotation](https://www.baeldung.com/spring-value-annotation)
2. [Spring Framework Documentation: @Value Annotations](https://docs.spring.io/spring-framework/reference/core/beans/annotation-config/value-annotations.html)
3. [DigitalOcean: Spring @Value Annotation](https://www.digitalocean.com/community/tutorials/spring-value-annotation)