深入理解Spring Boot start组件实现原理

731 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Spring Boot 自动配置原理

SpringBoot的优点这边不用多说,Springboot提供了一堆的starter,比如redis, kafka, nacos等等很多开源框架的启动器。使用起来非常方便。

Spring Boot 也提供了其它的启动器项目包括,包括用于开发特定类型应用程序的典型依赖项。

  • spring-boot-starter-web-services - SOAP Web Services
  • spring-boot-starter-web - Web 和 RESTful 应用程序
  • spring-boot-starter-test - 单元测试和集成测试
  • spring-boot-starter-jdbc - 传统的 JDBC
  • spring-boot-starter-hateoas - 为服务添加 HATEOAS 功能
  • spring-boot-starter-security - 使用 SpringSecurity 进行身份验证和授权
  • spring-boot-starter-data-jpa - 带有 Hibeernate 的 Spring Data JPA
  • spring-boot-starter-data-rest - 使用 Spring Data REST 公布简单的 REST 服务

等等。

Spring Boot 自动配置核心原理

三个核心注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass

@EnableAutoConfiguration 给容器导入META-INF/spring.factories 里定义的自动配置类。筛选有效的自动配置类。 每一个自动配置类结合对应的 xxxProperties.java 读取配置文件进行自动配置功能

以Nacos配置为例

image.png

Spring Boot 配置加载顺序

在 Spring Boot 里面配置的加载方式

  1. properties文件
  2. YAML文件
  3. 系统环境变量
  4. 命令行参数 当然还有其他的加载方式,比如nacos动态配置等等。

Spring Beans 里面直接使用这些配置文件中加载的值,如:

  1. 使用 @Value 注解直接注入对应的值,这能获取到 Spring中Environment 的值
  2. 使用 @ConfigurationProperties 注解把对应的值绑定到一个对象 4.直接获取注入 Environment 进行获取;

配置属性的方式很多,Spring boot使用了一种独有的 PropertySource 可以很方便的覆盖属性的值。

配置属性加载的顺序如下:

  1. 开发者工具 Devtools 全局配置参数;
  2. 单元测试上的 @TestPropertySource 注解指定的参数
  3. 单元测试上的 @SpringBootTest 注解指定的参数
  4. 命令行指定的参数,如 java -jar springboot.jar --name="Java技术栈"
  5. 命令行中的 SPRING_APPLICATION_JSONJSON 指定参数, 如 java -Dspring.application.json='{"name":"Java技术栈"}' -jar springboot.jar
  6. ServletConfig 初始化参数
  7. ServletContext 初始化参数;
  8. JNDI参数(如 java:comp/env/spring.application.json
  9. Java系统参数(来源:System.getProperties());
  10. 操作系统环境变量参数;
  11. RandomValuePropertySource 随机数,仅匹配:ramdom.*
  12. JAR包外面的配置文件参数(application-{profile}.properties(YAML)
  13. JAR包里面的配置文件参数(application-{profile}.properties(YAML)
  14. JAR包外面的配置文件参数(application.properties(YAML)
  15. JAR包里面的配置文件参数(application.properties(YAML)
  16. @Configuration配置文件上 @PropertySource 注解加载的参数;
  17. 默认参数(通过 SpringApplication.setDefaultProperties 指定);

数字小的优先级越高,即数字小的会覆盖数字大的参数值。