Recently, the company is upgrading SpringBoot and encountered some problems in the process of upgrading. I would like to briefly record and share with you. In addition, the program in this article is only sample code, not code for the company’s production environment.

What problems are encountered

After upgrading from SpringBoot1.x to Springboot2. x, resolve the compilation exception, run the program, and report an error when the program starts:

The error message clearly tells us the cause of the error:

The configuration attribute name com_shen is invalid

Invalid character: ‘_’, reason: The specification name should be kebab-case (delimited by ‘-‘), lowercase alphanumeric character, and must start with a letter

How to solve

Properties file contains the following configuration item:

com_shen.name=xiaohei
Copy the code

Corresponding Java program code:

@Getter
@Setter
@ConfigurationProperties(prefix = "com_shen")
public class Service {
    private String name;
}

Copy the code

In combination with the error log, we can easily solve this problem by removing _ from the configuration item and changing the configuration item name to com.shen.name.

The source code parsing

Do you think this is the end of the article? Not really. HHHHHH, let’s take a look at the internal source code of SpringBoot2.x. What, you don’t know where to start to look at the source code, it doesn’t matter, let’s take it step by step.

So if I go to @ConfigurationProperties,

In Spring, a lot of functionality is implemented through BeanPostProcessor. Also, the source code annotations in Spring are very carefully written. Through the source code comments we can guess may be ConfigurationPropertiesBindingPostProcessor in this class is responsible for @ ConfigurationProperties annotation support behind it.

PM ConfigurationPropertiesBindingPostProcessor class source code, find Override the BeanPostProcessor postProcessBeforeInitialization method in the class:

bind(bean, beanName, annotation);
@ConfigurationProperties

So, make a conditional breakpoint here and debug runs the project:

Debug shows that this method is indeed doing the property binding. And the underlying calls the org. Springframework. Boot. The context. The properties. The bind. Binder# bind (String, Bindable < T >, BindHandler) methods:

Call again in the bind method, another method is to bind (ConfigurationPropertyName) of (name), target, handler); Object, and through the name generated ConfigurationPropertyName ConfigurationPropertyName) of (name), by the method name we can guess, This method is probably responsible for resolving the Configuration Property Name, and the project startup error message is most likely thrown by this method. Click open source:

And found that in this method, Call InvalidConfigurationPropertyNameException. ThrowIfHasInvalidChars (name, ElementValidator getInvalidChars (elementValue)) ; . The Spring code naming is really elegant, and although the names are long, the source code reader can see what the method is doing at first glance.

Through the source code, we can see that the validity of characters in Configuration Property name is judged in SpringBoot, as shown in the figure above.

ElementValidator class is an inner class ConfigurationPropertyName. ConfigurationPropertyName is SpringBoot2.0 add a class, let’s read the notes in class, look at this class:

Machine translation results are as follows:

The configuration attribute name consisting of dot-separated elements. User-created names can contain characters “A-z”, “0-9”) and “-“, which must be lowercase and begin with an alphanumeric character. “-” is used for formatting only, i.e. “foo-bar” and “foobar” are considered equivalent. The “[” and”] “characters can be used to represent associated indexes (that is, Map keys or Collection indexes). Index names are unrestricted and case sensitive.

Here are some typical examples:

Spring. Main. Banner – mode for server hosts [0]. Name Log [org.springboot].level

Using the @ Value

We know that we can use @Value in SpringBoot as well as @ConfigurationProperties.

The Demo program is as follows:

@Getter
@Setter
@Component
public class Service {

    @Value("${com_shen.name}")
    private String name;
}
Copy the code

Application. The properties file:

com_shen.name=xiaohei
Copy the code

In this case, the project is still successfully started and the value of the com_Shen.name attribute is successfully obtained. That is, there is no expression restriction in the @value annotation.

Develop reading

Property Binding in Spring Boot 2.0: Spring. IO /blog/2018/0…


Welcome to our official account: