草稿
springboot默认的配置文件格式
properties
yaml
springboot-cli 默认生成脚手架项目默认配置文件格式是 properties
源码解析
ConfigFile…Listener
两种配置文件的解析类
选择策略
自定义实现思路
1.实现接口
2.自动装配 SPI 机制
springboot配置文件默认支持两种文件格式 , yml
和properties
springboot-cli 创建项目默认使用的是 (application.properties
) properties格式的文件
网址:
https://start.spring.io/
另外介绍一个网站也可以生成 springboot 脚手架项目
网址
https://start.aliyun.com/bootstrap.html
推荐使用 yml 文件格式
1.因为很多开源项目都是使用的 yml 格式
2.好多开源的中间件配置文件也是使用的 yml 格式
3.yml 比 properties 看上去更简洁 , 更有层次感
我认为 springboot 对于 spring 做的增强有一下几点:
增加了很多监听器以及监听事件
自动装配
内置服务器 tomcat
配置文件解析就是基于 监听器
实现的
加载配置文件的方法入口
public ConfigurableApplicationContext run(String... args) {
...
// 加载配置文件的方法入口
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
....
}
加载配置文件解析器
ConfigFileApplicationListener.java
加载默认的两个文件解析器
文件解析器通过 SPI 机制 , 在 spring-factories 文件中
PropertySourceLoader.java
接口
public interface PropertySourceLoader {
/**
获取文件的扩展名 , 即获取配置文件的后缀名
比如 yaml , yml , properties
*/
String[] getFileExtensions();
/**
加载配置文件属性到 PropertySouce
/*
List> load(String name, Resource resource) throws IOException;
}
查看 PropertiesPropertySourceLoader.java
, 并解释说明方法
public class PropertiesPropertySourceLoader implements PropertySourceLoader {
private static final String XML_FILE_EXTENSION = ".xml";
/**
加载 properties 格式的配置文件
*/
@Override
public String[] getFileExtensions() {
return new String[] { "properties", "xml" };
}
/**
加载配置文件内容
*/
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
Map<String, ?> properties = loadProperties(resource);
if (properties.isEmpty()) {
return Collections.emptyList();
}
return Collections
.singletonList(new OriginTrackedMapPropertySource(name, Collections.unmodifiableMap(properties), true));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Map<String, ?> loadProperties(Resource resource) throws IOException {
String filename = resource.getFilename();
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
return (Map) PropertiesLoaderUtils.loadProperties(resource);
}
return new OriginTrackedPropertiesLoader(resource).load();
}
}
JsonPropertySourceLoader.java
package com.example.config;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JsonPropertySourceLoader implements PropertySourceLoader {
private static final Log logger = LogFactory.getLog(JsonPropertySourceLoader.class);
@Override
public String[] getFileExtensions() {
//这个方法表明这个类支持解析以json结尾的配置文件
return new String[]{"json"};
}
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
ReadableByteChannel readableByteChannel = resource.readableChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate((int) resource.contentLength());
//将文件内容读到 ByteBuffer 中
readableByteChannel.read(byteBuffer);
//将读出来的字节转换成字符串
String content = new String(byteBuffer.array());
// 将字符串转换成 JSONObject
JSONObject jsonObject = JSON.parseObject(content);
Map<String, Object> map = new HashMap<>(jsonObject.size());
//将 json 的键值对读出来,放入到 map 中
for (String key : jsonObject.keySet()) {
map.put(key, jsonObject.getString(key));
}
logger.info("自定义实现 PropertySourceLoader 接口 , 重写 load 方法");
return Collections.singletonList(new MapPropertySource("jsonPropertySource", map));
}
}
META-INF/spring.factories
org.springframework.boot.env.PropertySourceLoader=\
com.example.config.JsonPropertySourceLoader
{
"server.port":4444,
"user.userName": "测试是否会中文乱码",
"user.age": 18
}
测试springboot自动装配的属性是否生效
测试自定义属性注入是否生效
定义自定义属性注入测试类
@Component
public class UserTestValue {
@Value("${user.userName}")
public String userName;
@Value("${user.age}")
public String age;
}
测试获取属性
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
ApplicationContext ac = SpringApplication.run(SpringbootDemoApplication.class, args);
UserTestValue userTestValue = ac.getBean(UserTestValue.class);
/**
* 测试 @Value 注解
* 不需要 javabean 实现 set/get 方法
*/
System.out.println("测试 @Value 注解**********************************");
System.out.println("user.userName = " + userTestValue.userName);
System.out.println("user.age = " + userTestValue.age);
}
}
控制台打印
测试 @Value 注解**********************************
user.userName = 测试是否会中文乱码
user.age = 18
****************************");
System.out.println("user.userName = " + userTestValue.userName);
System.out.println("user.age = " + userTestValue.age);
}
}
控制台打印
> 测试 @Value 注解**********************************
> user.userName = 测试是否会中文乱码
> user.age = 18
![image-20221027142032730](https://img-blog.csdnimg.cn/img_convert/4933ef4c7ecdac5c6a5443358aa80496.png)