写点什么

springboot 自动配置原理

作者:喝水不抬头
  • 2023-02-12
    上海
  • 本文字数:2983 字

    阅读完需:约 10 分钟

一、Spring Boot 简介

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.


Spring Boot 用来简化 Spring 应用开发,约定大于配置, 去繁从简,just run 就能创建一个独立的,产品级别的应用。简言之,Spring Boot 就是 Spring,它只是做了一些没有它你自己也会做的事情,比如 bean 配置、版本依赖。



Spring Boot 的主要特性如下:


Features

  • Create stand-alone Spring applications

  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)

  • Provide opinionated 'starter' dependencies to simplify your build configuration

  • Automatically configure Spring and 3rd party libraries whenever possible

  • Provide production-ready features such as metrics, health checks, and externalized configuration

  • Absolutely no code generation and no requirement for XML configuration


每一个特性都在通过自己的方式简化 Spring 应用程序的开发。 我们今天的重点是自动配置,也会附带说一些起步依赖相关的东西。

二、Hello World 入门

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId> <artifactId>spring-boot-01-helloworld</artifactId> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies></project>
复制代码


@RestControllerpublic class HelloController {    @RequestMapping("/hello")    String hello() {
return "你好,World!"; }}
复制代码


// @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用@SpringBootApplicationpublic class HelloWorldMainApplication {
public static void main(String[] args) throws Exception { // Spring应用启动起来 SpringApplication.run(HelloWorldMainApplication.class, args); }}
复制代码


运行 main 方法后,浏览器中输入 http://localhost:8080/hello,显示如下:



小结如下:

(1)从父项目 spring-boot-starter-parent 继承了通用的依赖

(2)spring-boot-starter-web 帮我们导入了 web 模块正常运行所依赖的组件

(3)运行 main 方法后,加载主程序类所在的包及子包的组件,并开启自动配置,将大量的自动配置组件添加到容器中。

三、起步依赖

如果没有起步依赖,对于上面的 HelloWord 入门 web 程序的依赖引入,你会考虑哪些呢?


  • 引入哪些依赖

  • 引入依赖的版本

  • 依赖之间是否可以兼容

  • ......


来看看 spring boot 如何通过提供众多起步依赖降低项目依赖的复杂度?起步依赖本质上是一个 Maven 项对象模型(Project Object Model,POM),定义了对其他库的传递依赖,加在一起即支持某项功能。如果你需要一个 web 应用程序,则添加 spring-boot-starter-web 起步依赖,如果你需要能在 Spring Boot 上下文里运行集成测试的库,则添加 spring-boot-starter-test 起步依赖。Spring Boot 将所有的功能场景都抽取出来,对应不同的起步依赖。要用什么功能,只需要在项目里面引入这些功能对应的起步依赖,相关的依赖都会导入进来。Spring Boot 经过了足够的测试,确保引入的全部依赖都能相互兼容。


起步依赖的命名都暗示了它们提供的某种或某类功能,可以参考https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#using-boot-starter

四、自动配置原理

Spring Boot 启动的时候加载主程序类,开启自动配置功能。在这里将注解发挥到了极致,了解了自动配置功能涉及的核心注解,也就知道了 spring boot 是如何进行自动配置的。


3.1 SpringBootApplication

@SpringBootConfiguration 标注在某个类上,表示这是一个 Spring Boot 的配置类。这个注解等价于 Configuration+EnableAutoConfiguration+ComponentScan

3.2 EnableAutoConfiguration

自动配置的核心注解,核心见 3.3 和 3.4

3.3 AutoConfigurationPackage

将 AutoConfigurationPackages.Registrar.class 对应的实例添加到容器中,该实例会存储用户自定义的自动配置包列表。 从截图中可以看出,主程序类所在的包会作为自动配置包存储下来。



Spring Boot 其它地方可以通过静态方法 AutoConfigurationPackages.get 获取这个自动配置包列表,从而进行自动扫描,如:


protected String[] getPackagesToScan() {
List<String> packages = EntityScanPackages.get(this.beanFactory).getPackageNames();
if (packages.isEmpty() && AutoConfigurationPackages.has(this.beanFactory)) { packages = AutoConfigurationPackages.get(this.beanFactory); } return packages.toArray(new String[packages.size()]); }
复制代码

3.4 Import(EnableAutoConfigurationImportSelector.class)

导入组件的选择器,Spring Boot 在启动的时候从 EnableAutoConfiguration 类路径下的 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的值,这些值对应的组件经过筛选后就会被添加到容器中



3.5 @Conditional 扩展注解

自动配置类必须在一定的条件下才能生效,通过 @Conditional 及扩展注解,不同的自动配置组件可以灵活地配置生效条件,比如下面这个自动配置组件在以下两个条件均满足时才会被加载到容器中:


  • 当前是 web 环境

  • 类路径下存在 DispatcherServlet.class


@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@Configuration@ConditionalOnWebApplication@ConditionalOnClass(DispatcherServlet.class)@AutoConfigureAfter(EmbeddedServletContainerAutoConfiguration.class)public class DispatcherServletAutoConfiguration {    ......}
复制代码


@Conditional 常见扩展注解列举如下:

我们可以通过启用 debug=true 属性,来让控制台打印自动配置报告,这样我们就可以更方便地知道哪些自动配置类被加载到了容器中。

五、自定义配置

spring boot 在装配自动配置组件时,使用默认的配置,可以通过编写配置文件来替换这些默认的配置。如何知道配置文件中可以编写哪些配置呢?接下来以自动配置组件 HttpEncodingAutoConfiguration 为例进行介绍。



HttpEncodingProperties 类上注解 EnableConfigurationProperties 的作用是支持从配置文件中获取指定的值和 bean 的属性进行绑定,HttpEncodingProperties 类中定义了哪些属性,我们就可以在自己定义的配置文件中重新配置哪些属性。




charset 默认的编码格式为 UTF-8,尝试设置为 ISO-8859-1 后,中文会出现乱码




发布于: 刚刚阅读数: 6
用户头像

还未添加个人签名 2018-05-15 加入

还未添加个人简介

评论

发布
暂无评论
springboot自动配置原理_喝水不抬头_InfoQ写作社区