什么是Spring Boot ?

Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。spring Boot采用约定优于配置的方式,大量的减少了配置文件的使用。
Spring Boot可以理解成是Spring框架的扩展,能够简化各框架的配置文件;快速构建web应用;而且内置了tomcat,web项目无需打包部署,可以直接运行,也可以打成jar包,直接在线上环境运行。

什么是“约定优于配置”?

“约定优于配置”,其实一种按约定编程的软件设计范式,目的在于减少软件开发人员在工作中的各种繁琐的配置。
Spring Boot的产生很好的遵循了“约定优于配置”这一理念,这才使得它变得如此简单、快速和便捷。那这一理念在Spring Boot中的具体表现有哪些呢?

  • 一系列的Starter简化框架的整合
  • 运行方式采用内置tomcat容器,可以使用jar包部署项目
  • 默认配置文件properties和yaml,语法简洁、功能强大
  • 注解实现自动配置

    什么是Starter ?

    Spring Boot中的Starter可以理解成是一系列依赖的组合,Spring Boot还帮助我们完成了它们之间的配置。
    例如,我们想在Spring Boot中使用Spring MVC。如果不是Spring Boot项目,我们需要引入spring-web、spring-webmvc、spring-aop等一系列依赖。但是在Spring Boot项目中,只需要引入spring-boot-starter-web即可。

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-web</artifactId>
    4. </dependency>

    Starter的依赖命名都遵循相同的规则:spring-boot-starter-*。例如常用的Starter有:

  • spring-boot-starter-data-jpa

  • spring-boot-starter-redis
  • spring-boot-starter-security
  • spring-boot-starter-test
  • spring-boot-starter-thymeleaf
  • … …

*-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
所有场景启动器最底层的依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter</artifactId>
  4. <version>2.3.4.RELEASE</version>
  5. <scope>compile</scope>
  6. </dependency>

Spring Boot的特点

  • Create stand-alone Spring applications
  • 创建独立Spring应用
  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
  • 内嵌web服务器
  • Provide opinionated ‘starter’ dependencies to simplify your build configuration
  • 自动starter依赖,简化构建配置
  • Automatically configure Spring and 3rd party libraries whenever possible
  • 自动配置Spring以及第三方功能
  • Provide production-ready features such as metrics, health checks, and externalized configuration
  • 提供生产级别的监控、健康检查及外部化配置
  • Absolutely no code generation and no requirement for XML configuration
  • 无代码生成、无需编写XML

SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架

自动配置原理

依赖管理

  1. 依赖管理这个是我们的项目pom.xml编写的,管理项目的资源过滤及插件
  2. <parent>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-parent</artifactId>
  5. <version>2.3.4.RELEASE</version>
  6. </parent>
  7. spring-boot-starter-parent的工程又依赖了spring-boot-dependencies,
  8. 管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心,
  9. 以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;
  10. <parent>
  11. <groupId>org.springframework.boot</groupId>
  12. <artifactId>spring-boot-dependencies</artifactId>
  13. <version>2.3.4.RELEASE</version>
  14. </parent>

修改默认版本号
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置在properties节点下修改版本号

  1. <properties>
  2. <mysql.version>5.1.43</mysql.version>
  3. </properties>

自动配置

常用框架对应的JavaConfig类都已经编写好了,springboot启动的时候会一个一个的进行读取,读取时会先根据条件注解进行判断,看是否满足条件,满足条件后才会读取配置类然后去配置对应的框架。
1. Springboot启动后,读取程序的启动类时,就会读取到@SpringBootApplication注解

  1. @SpringBootApplication
  2. public class DateDemoApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(DateDemoApplication.class, args);
  5. }
  6. }

2. @SpringBootApplication注解又包含了 @EnableAutoConfiguration注解

  1. // 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)或enum声明
  2. @Target(ElementType.TYPE)
  3. // 注解的生命周期,保留到class文件中(三个生命周期)
  4. @Retention(RetentionPolicy.RUNTIME)
  5. // 表明这个注解应该被javadoc记录
  6. @Documented
  7. // 子类可以继承该注解
  8. @Inherited
  9. // 继承了Configuration,表示当前是注解类
  10. @SpringBootConfiguration
  11. // 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助
  12. @EnableAutoConfiguration
  13. // 扫描路径设置
  14. @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  15. @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
  16. public @interface SpringBootApplication {
  17. /**
  18. * Exclude specific auto-configuration classes such that they will never be applied.
  19. * @return the classes to exclude
  20. */
  21. @AliasFor(annotation = EnableAutoConfiguration.class)
  22. Class<?>[] exclude() default {};
  23. ...
  24. }
  25. @Target(ElementType.TYPE)
  26. @Retention(RetentionPolicy.RUNTIME)
  27. @Documented
  28. @Configuration
  29. public @interface SpringBootConfiguration {
  30. ...
  31. }
  1. @EnableAutoConfiguration注解导入了AutoConfigurationImportSelector类,
    @Import(AutoConfigurationImportSelector.class)
    @EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效; ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage // @Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ; // AutoConfigurationImportSelector :自动配置导入选择器 @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {

    /**

    • Environment property that can be used to override when auto-configuration is
    • enabled. */ String ENABLED_OVERRIDE_PROPERTY = “spring.boot.enableautoconfiguration”;

}

  1. 4. `@AutoConfigurationPackage` :**自动配置包**
  2. ```java
  3. // @import :Spring底层注解@import , 给容器中导入一个组件
  4. // Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 ;
  5. @Target(ElementType.TYPE)
  6. @Retention(RetentionPolicy.RUNTIME)
  7. @Documented
  8. @Inherited
  9. @Import(AutoConfigurationPackages.Registrar.class)
  10. public @interface AutoConfigurationPackage {
  11. ...
  12. }
  1. AutoConfigurationImportSelector.class中,定义了一个方法getCandidateConfigurations,进入getCandidateConfigurations方法,getCandidateConfigurations会到classpath下的读取META-INF/spring.factories文件的配置

    1. protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    2. List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
    3. getBeanClassLoader());
    4. Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
    5. + "are using a custom packaging, make sure that file is correct.");
    6. return configurations;
    7. }
  2. spring.factories文件在spring-boot-autoconfigure-2.3.7.RELEASE.jar的META-INF中,spring.factories文件中声明了很多java配置类,但是每个配置类都是需要满足一定的条件才会执行(例如: @ConditionalOnClass 、 @ConditionalOnProperty、 @ConditionalOnMissingBean等)

image.png

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
  3. org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
  4. org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
  5. org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
  6. org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
  7. org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
  8. org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
  9. org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
  10. org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
  11. org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
  12. org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
  13. ...
  1. 随便打开一个自动配置文件,比如说WebMvcAutoConfiguration.class ```java @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
    1. ValidationAutoConfiguration.class })
    public class WebMvcAutoConfiguration {

} `` 从WebMvcAutoConfiguration`这个类中使用的注解可以看出,要完成自动配置是有依赖条件的。
这些是springboot特有的,常见的条件依赖注解有:

@ConditionalOnSingleCandidate,仅在当前上下文中存在某个bean时,才会实例化这个Bean。
@ConditionalOnClass,某个class位于类路径上,才会实例化这个Bean。
@ConditionalOnExpression,当表达式为true的时候,才会实例化这个Bean。
@ConditionalOnMissingBean,仅在当前上下文中不存在某个bean时,才会实例化这个Bean。
@ConditionalOnMissingClass,某个class在类路径上不存在的时候,才会实例化这个Bean。
@ConditionalOnNotWebApplication,不是web应用时才会实例化这个Bean。
@AutoConfigureAfter,在某个bean完成自动配置后实例化这个bean。
@AutoConfigureBefore,在某个bean完成自动配置前实例化这个bean。

所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。\

总结

1、@Configuration&与@Bean->基于java代码的bean配置
2、@Conditional->设置自动配置条件依赖
3、@EnableConfigurationProperties与@ConfigurationProperties->读取配置文件转换为bean。
4、@EnableAutoConfiguration、@AutoConfigurationPackage 与@Import->实现bean发现与加载。
5、@EnableAutoConfiguration自动配置从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

springboot启动加载所有的配置类(127个),按需加载所需配置类。
**SpringBoot自动配置原理 - 图2