Getting Started with Spring: Runtime Value Injection

Spring provides two ways to inject values at runtime:

  1. Property placeholder
  2. Spring Expression Language (SpEL)

1. Property placeholders

1.1 Injection External Value

1.1.1 Using Environment

Normally, we put some values in the configuration file and then inject them into some fields when the program runs.

Suppose we have a test.properties configuration file that reads as follows:

book.author=wangyunfei
book.name=spring boot
author.age=30

Now we want to assign this value to the fields bookAuthor and bookName when the program is running, so how do we do that?

First, create a new configuration class, ExpressiveConfig, as follows:

package chapter03.el;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@ComponentScan
@PropertySource("classpath:chapter03/el/test.properties")
public class ExpressiveConfig {
    @Autowired
    private Environment environment;

    public void outputResource() {
        System.out.println("book.name:" + environment.getProperty("book.name"));
        System.out.println("book.author:" + environment.getProperty("book.author"));
    }
}

Here we use the @PropertySource annotation to reference the test.properties configuration file, which is located in the chapter03.el package.

This property file is loaded into Spring's Environment, and then we can call the getProperty() method to get the property value.

Create a new Main class and add the following test code to its main() method:

package chapter03.el;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ExpressiveConfig.class);

        ExpressiveConfig expressiveConfig = context.getBean(ExpressiveConfig.class);

        expressiveConfig.outputResource();

        context.close();
    }
}

Run the code and find a java.io.FileNotFoundException exception thrown, as follows:

As you can see from the error message, this is a hint that the file chapter03/el/test.properties cannot be found. Why?

With this in mind, let's look at the compiled code in the target directory, as follows:

As you can see from the diagram, our new test.properties and test.txt files are not compiled into the target directory, so exceptions are thrown.

This is because our new files are located in the chapter03.el package and IDEA does not automatically copy them to the target directory by default, but we can add the following configuration to pom.xml to solve this problem:

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.txt</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
    </resources>
</build>

Here we specify the txt and properties files, and you can continue to add <include>tags to specify files such as xml if you want.

Run the test code again with the output log as follows:

book.name:spring boot

book.author:wangyunfei

At this point, the target directory already contains the two files we created:

If the specified property value does not exist, getProperty() returns null, as follows:

String workCity = environment.getProperty("author.workcity");
System.out.println("author.workcity:" + workCity);

Output results:

author.workcity:null

getProperty() also provides an overload to specify a default value when the specified property value does not exist:

String workCity = environment.getProperty("author.workcity", "Shanghai");
System.out.println("author.workcity:" + workCity);

Output results:

author.workcity:Shanghai

If you want the attribute value to exist, you can use the getRequiredProperty() method, which throws a java.lang.IllegalStateException exception when the attribute value does not exist:

String workCity = environment.getRequiredProperty("author.workcity");
System.out.println("author.workcity:" + workCity);

getProperty() also provides an overload that specifies the type of return value, such as the Integer type we want to return:

Integer authorAge = environment.getProperty("author.age", Integer.class);
System.out.println("author.age:" + authorAge);

Output results:

author.age:30

getProperty() also provides an overload to specify not only the default value but also the return value type when the specified property value does not exist:

boolean isMan = environment.getProperty("author.isMan", Boolean.class, true);
System.out.println("author.isMan:" + isMan);

Output results:

author.isMan:true

1.1.2 Use attribute placeholders

In addition to using Environment to get external property values, we can also use property placeholders to get them.

In Spring assemblies, placeholders are in the form of property names wrapped in'${...}'.

The new Book class is as follows:

package chapter03.el;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Book {
    @Value("${book.name}")
    private String bookName;

    @Value("${book.author}")
    private String bookAuthor;

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookAuthor() {
        return bookAuthor;
    }

    public void setBookAuthor(String bookAuthor) {
        this.bookAuthor = bookAuthor;
    }
}

You can see that we added the @Value annotation to the field, and the value passed by the parameter is the property placeholder, which is used to get the property value specified in the property file.

Then add the following code to the ExpressiveConfig configuration class:

@Autowired
private Book book;

public void outputResource() {
     System.out.println("book.name:" + book.getBookName());
     System.out.println("book.author:" + book.getBookAuthor());
}

Output results:

book.name:spring boot

book.author:wangyunfei

2. Spring expression language

Spring Expression Language (SpEL) is a very flexible expression language that can assemble values into bean attributes or constructor parameters in a powerful and concise way, and the expressions used in this process calculate values at runtime.

The SpEL expression is placed in'#{...}', while the property placeholder mentioned earlier is placed in'${...}'.

Next, let's look at how the Spring expression language is used in a scenario.

2.1 Reference system attribute values

Add the following code to ExpressiveConfig:

@Value("#{systemProperties['os.name']}")
private String osName;

public void outputResource() {
    System.out.println("os.name:" + osName);
}

Output results:

os.name:Windows 7

2.2 Properties and methods of reference bean s

First, create a new class DemoService as follows:

package chapter03.el;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class DemoService {
    @Value("DemoService Class another attribute")
    private String another;

    public String getAnother() {
        return another;
    }

    public void setAnother(String another) {
        this.another = another;
    }
}

Then add the following code to ExpressiveConfig:

@Value("#{demoService.another}")
private String fromAnother;

public void outputResource() {
    System.out.println("demoService.another:" + fromAnother);
}

The demoService in the expression is the ID of the DemoService bean, and another is its property.

Output results:

DemoService.another:another property of DemoService class

The expression can also be modified to call the bean's method:

@Value("#{demoService.getAnother()}")
private String fromAnother;

The output does not change, just from the call property to the call method.

After calling a method, you can continue to call other methods, such as toUpperCase(), on the return value of the method:

@Value("#{demoService.getAnother()?.toUpperCase()}")
private String fromAnother;

The'?''operator is used to avoid NullPointerException in code when demoService.getAnother() returns null.

The output at this point is:

DemoService.another:ANOTHER attribute of DEMOSERVICE class

2.3 Use types in expressions

Use an expression to generate a random number:

@Value("#{T(java.lang.Math).random()}")
private double randomNumber;

public void outputResource() {
    System.out.println("randomNumber:" + randomNumber);
}

Here we use T() to reference the java.lang.Math class and then call its static method random().

Output results:

randomNumber:0.6801944394506442

2.4 Using Operators

In the example above, after generating a random number, we can also use the multiplication operator as follows:

@Value("#{T(java.lang.Math).random() * 100.0}")
private double randomNumber;

We can also use the'+'operator to stitch strings in expressions as follows:

@Value("#{book.getBookName() + ' write by ' + book.getBookAuthor()}")
private String bookDescr;

public void outputResource() {
    System.out.println("bookDescr:" + bookDescr);
}

Where book is the ID of the Book bean, the output is as follows:

bookDescr:spring boot write by wangyunfei

Ternary operators can also be used in expressions:

@Value("#{systemProperties['os.name'] == 'Windows 7'?'Windows':'Linux'}")
private String osType;

public void outputResource() {
    System.out.println("osType:" + osType);
}

Because my computer system is Windows 7, the output is as follows:

osType:Windows

SpEL also supports many operators, but here are just a few common examples that interested students can explore in depth themselves.

3. Source Code and Reference

Source address: https://github.com/zwwhnly/spring-action.git Welcome to download.

Craig Walls The Spring Actual War (4th Edition)

Wang Yunfei, Subverters of Java EE Development: Spring Boot Actual Warfare

Solution for IDEA maven project src source code resource files not automatically copied to classes folder

4. Finally

Play a small advertisement, welcome to sweep code and pay attention to the WeChat public number: "Shencheng Foreigners". Share the dried Java technology regularly, so we can make progress together.

Keywords: Java Spring Attribute Windows

Added by mtucker6784 on Fri, 16 Aug 2019 04:40:57 +0300