你只知道@Value?设置server.port就能定义端口号是如何实现的?springboot读取配置文件的多种方式以及原理解析

  • 一、SpringBoot全局配置文件优先级
  • 二、属性注入常用注解
  • 1、@Value注入
  • 2、@ConfigurationProperties批量注入
  • 三、从源码分析server.port是如何生效的


一、SpringBoot全局配置文件优先级

全局配置文件能够对一些默认值进行修改,以及自定义配置。Spring Boot使用一个application.properties或者application.yml文件作为全局配置文件,文件系统和优先级如下:

  1. 项目根目录/config/
  2. 项目根目录/
  3. classpath:/config/ 等同于 /resources/config/
  4. classpath:/ 等同于 ./resources/

springboot后端的端口怎么看 springboot配置端口号_java

其他注意事项:

  • 配置相同的属性时,按照优先级为准,后面读取到的不会覆盖前面的。
  • 同一目录下既有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中的源码配置文件找到,如下图:

springboot后端的端口怎么看 springboot配置端口号_spring boot_02

三、从源码分析server.port是如何生效的

当我们在配置文件中定义server.port=8081时,那么我们就可以通过8081端口访问该web服务,那么spring-boot是如何获取到iserver.port的配置的呢?

1.当我们在idea中按住Ctrl键,使用鼠点击可以进入org.springframework.boot.autoconfigure.web.ServerProperties的setPort方法.

springboot后端的端口怎么看 springboot配置端口号_springboot后端的端口怎么看_03

部分源码如下:

@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()方法中

springboot后端的端口怎么看 springboot配置端口号_java_04


3.通过查看类的源码发现

ServletWebServerFactoryCustomizer.java的ServerProperties属性只能是通过该类提供的2个构造器注入进来,继续跟踪这两个构造器调用栈发现是在

org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration#servletWebServerFactoryCustomizer()的@bean注解注入进来

springboot后端的端口怎么看 springboot配置端口号_spring boot_05


springboot后端的端口怎么看 springboot配置端口号_配置文件_06


至此我们发现server.port是通过@ConfigurationProperties注解赋值,并通过自动装配创建web容器时得到使用。