你只知道@Value?设置server.port就能定义端口号是如何实现的?springboot读取配置文件的多种方式以及原理解析
- 一、SpringBoot全局配置文件优先级
- 二、属性注入常用注解
- 1、@Value注入
- 2、@ConfigurationProperties批量注入
- 三、从源码分析server.port是如何生效的
一、SpringBoot全局配置文件优先级
全局配置文件能够对一些默认值进行修改,以及自定义配置。Spring Boot使用一个application.properties或者application.yml文件作为全局配置文件,文件系统和优先级如下:
- 项目根目录/config/
- 项目根目录/
- classpath:/config/ 等同于 /resources/config/
- classpath:/ 等同于 ./resources/
其他注意事项:
- 配置相同的属性时,按照优先级为准,后面读取到的不会覆盖前面的。
- 同一目录下既有properties又有yml文件时,如果2.4.0之前的版本以properties>yml,2.4.0之后的版本以yml >properties为准。
- 同时我们可以指定的路径的配置文件,在运行程序时设置
- 松散绑定,如java实体字段名
private String userName;
则配置文件可以写成如下方式均可。
userName=root
user-name=root
user_name=root
USER_NAME=root
java -jar myproject.jar --spring.config.location=D:/application.properties
二、属性注入常用注解
1、@Value注入
在spring的bean对象中使用@Value注解注入属性,例如:
// 只要是注入spring的bean的注解均可以,如@Service、@Component等。
@Configuration
public class DatasourceConfig{
@Value("${jdbc.username}")
private String username;
//可以不提供getting/setting
}
2、@ConfigurationProperties批量注入
配置文件内容如下
jdbc:
username: root
password: root
mysqlInfo:
driverClass: com.mysql.jdbc.Driver
@Configuration
//一定要使用前缀
@CofigurationProperties(prefix="jdbc")
public class DatasourceConfig{
private String username;
private String password;
//这是一个类,里面有一个driverClass属性;
private MysqlInfo mysqlInfo;
//需要提供getting、setting方法
public void setUsername(String username) {
this.username = username;
}
//此处省略更多setting/getting方法。
}
或者DatasourceConfig 仅为getting/setting方法。
@Configuration
public class DbConfig{
@Bean
@CofigurationProperties(prefix="jdbc")
public DatasourceConfig database(){
return new DatasourceConfig();
}
}
如果想要在idea等工具填写配置时有自动提示功能,需要引入如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
或者在
resources/META-INF/spring-configuration-metadata.json
或者
additional-spring-configuration-metadata.json
配置文件的json格式可以查看springboot中的源码配置文件找到,如下图:
三、从源码分析server.port是如何生效的
当我们在配置文件中定义server.port=8081时,那么我们就可以通过8081端口访问该web服务,那么spring-boot是如何获取到iserver.port的配置的呢?
1.当我们在idea中按住Ctrl键,使用鼠点击可以进入org.springframework.boot.autoconfigure.web.ServerProperties
的setPort方法.
部分源码如下:
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
/**
* Server HTTP port.
*/
private Integer port;
/**
* Network address to which the server should bind.
*/
private InetAddress address;
@NestedConfigurationProperty
private final Http2 http2 = new Http2();
private final Servlet servlet = new Servlet();
private final Tomcat tomcat = new Tomcat();
public Integer getPort() {
return this.port;
}
public void setPort(Integer port) {
this.port = port;
}
}
这个类的注解使用的是@ConfigurationProperties注解识别,通过第二章第二点的介绍我们知道了这个注解的作用。
2.通过ServerProperties .java
的getPort方法我们继续跟踪,发现调用地方在org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer#customize()
方法中
3.通过查看类的源码发现
ServletWebServerFactoryCustomizer.java的ServerProperties属性只能是通过该类提供的2个构造器注入进来,继续跟踪这两个构造器调用栈发现是在
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration#servletWebServerFactoryCustomizer()
的@bean注解注入进来
至此我们发现server.port是通过@ConfigurationProperties注解赋值,并通过自动装配创建web容器时得到使用。