Project address
springboot_01
We should have seen the
load(), getPropertySources(), and addLast()
methods in the previous article . Let's write a simple configuration file reading program.
Let's take a look at the last load() method we saw before.
private void load(PropertySourceLoader loader, String location, Profile profile, DocumentFilter filter,
DocumentConsumer consumer) {
Resource[] resources = getResources(location);
for (Resource resource : resources) {
try {
if (resource == null || !resource.exists()) {
if (this.logger.isTraceEnabled()) {
StringBuilder description = getDescription("Skipped missing config ", location, resource,
profile);
this.logger.trace(description);
}
continue;
}
if (!StringUtils.hasText(StringUtils.getFilenameExtension(resource.getFilename()))) {
if (this.logger.isTraceEnabled()) {
StringBuilder description = getDescription("Skipped empty config extension ", location,
resource, profile);
this.logger.trace(description);
}
continue;
}
String name = "applicationConfig: [" + getLocationName(location, resource) + "]";
List<Document> documents = loadDocuments(loader, name, resource);
if (CollectionUtils.isEmpty(documents)) {
if (this.logger.isTraceEnabled()) {
StringBuilder description = getDescription("Skipped unloaded config ", location, resource,
profile);
this.logger.trace(description);
}
continue;
}
List<Document> loaded = new ArrayList<>();
for (Document document : documents) {
if (filter.match(document)) {
addActiveProfiles(document.getActiveProfiles());
addIncludedProfiles(document.getIncludeProfiles());
loaded.add(document);
}
}
Collections.reverse(loaded);
if (!loaded.isEmpty()) {
loaded.forEach((document) -> consumer.accept(profile, document));
if (this.logger.isDebugEnabled()) {
StringBuilder description = getDescription("Loaded config file ", location, resource,
profile);
this.logger.debug(description);
}
}
}
catch (Exception ex) {
StringBuilder description = getDescription("Failed to load property source from ", location,
resource, profile);
throw new IllegalStateException(description.toString(), ex);
}
}
}
Here we mentioned that List<Document> documents = loadDocuments(loader, name, resource);
this line of code is to read the configuration file and see how it is implemented.
You can see from the debug information that the value of documents is empty. Our configuration file is a key-value pair, so it may be the data obtained in the part circled above.
By looking at the debug console, it is indeed in this position.
So let's check this method.
These two classes are very familiar, but enter different classes for different configuration file suffixes. You may understand all of them when you
enter this.process(callback, yaml, resource);
here. new UnicodeReader(resource.getInputStream());
Read file data.
Back again
private List<Document> loadDocuments(PropertySourceLoader loader, String name, Resource resource)
throws IOException {
DocumentsCacheKey cacheKey = new DocumentsCacheKey(loader, resource);
List<Document> documents = this.loadDocumentsCache.get(cacheKey);
if (documents == null) {
List<PropertySource<?>> loaded = loader.load(name, resource);
documents = asDocuments(loaded);
this.loadDocumentsCache.put(cacheKey, documents);
}
return documents;
}
In this methoddocuments = asDocuments(loaded);
Then the basic steps are understood.
- First read the configuration file information.
- Packaging properties
- getPropertySources()
- addLast()
Okay, now we start to code
Create a my.properties file.
name=龙小虬
As we mentioned before,
we scanned the spring.factories file org.springframework.boot.SpringApplicationRunListener
, so we also create a spring.factories file. Configuration information
org.springframework.boot.SpringApplicationRunListener=\
com.lxq.listener.MySpringApplicationRunListeners
And create MySpringApplicationRunListeners.java
package com.lxq.listener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
/**
* @author 龙小虬
* @date 2021/3/24 14:57
*/
public class MySpringApplicationRunListeners implements SpringApplicationRunListener {
@Override
public void starting() {
System.out.println(">>>>>starting<<<<<");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
// 先读取配置文件到程序中,然后放入SpringBoot中
Properties properties = new Properties();
try {
// 1. 读取我们的my.properties文件,配置编码,防止中文乱码
properties.load(new InputStreamReader(this.getClass().getClassLoader().
getResourceAsStream("my.properties"), "GB2312"));
// 2. 读取名称名称为my
PropertySource propertySource = new PropertiesPropertySource("my", properties);
//3. 将资源添加到项目中
MutablePropertySources propertySources = environment.getPropertySources();
//4. 通过api接口可以将配置文件读取 到SpringBoot项目中
propertySources.addLast(propertySource);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Create MyController.java
package com.lxq.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 龙小虬
* @date 2021/3/24 14:53
*/
@RestController
public class MyController {
@Value("${name}")
private String name;
@RequestMapping(value = "/test",produces = "text/plain;charset=UTF-8")
public String test(){
return "手动注入my.properties"+name;
}
}
Run the code. Report an error directly
getDeclaredConstructor
Obviously the reflection execution is wrong.
So let's see where the imitation is wrong.
Find this class.
You can see that this class is constructed with parameters, while we are constructed without parameters. So we also add one. In fact, it can be seen in another place. We mentioned that the starting() method will be called back. So we look at him.
Then see that the listener.starting() method
has parameter construction here, so we really have a problem with this step.
We add a parameter structure in MySpringApplicationRunListeners.java
private final SpringApplication application;
private final String[] args;
public MySpringApplicationRunListeners(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
}
Run and visithttp://localhost:8090/test