springboot-spring源码系列(十三)

128 阅读6分钟

终于到了springboot的源码了

springboot的基本认识

不管是spring cloud alibaba还是spring cloud netflix,都是基于springboot这个微框架来构建的,所以我希望花一 点时间来讲一下springboot

1.什么是 springboot

对于spring框架,我们接触得比较多的应该是spring mvc、和 spring。而spring的核心在于 IOC(控制反转)和DI(依赖注入)。而这些框架在使用的过程中会需要配置大量的xml,或者需要做很多繁琐的配置。 springboot 框架是为了能够帮助使用 spring 框架的开发者快速高效的构建一个基于 spirng 框架以及 spring 生态体系的应用解决方案。它是对“约定优于配置”这个理念下 的一个最佳实践。因此它是一个服务于框架的框架,服务的范围是简化配置文件。

2.约定优于配置的体现

约定优于配置的体现主要是

  1. maven的目录结构 a) 默认有resources文件夹存放配置文件 b) 默认打包方式为jar
  2. spring-boot-starter-web中默认包含spring mvc相关依赖以及内置的tomcat容器,使得构建一个web应用更加简单
  3. 默认提供application.properties/yml文件
  4. 默认通过 spring.profiles.active 属性来决定运行环境时读取的配置文件
  5. EnableAutoConfiguration 默认对于依赖的starter进行自动装载

3.从SpringBootApplication注解入手

为了揭开 springboot 的奥秘,我们直接从Annotation入手,看看@SpringBootApplication里面,做了什么?打开SpringBootApplication这个注解,可以看到它实际上 是一个复合注解 SpringBootApplication本质上是由3个注解组成,分别是

  1. @Configuration
  2. @EnableAutoConfiguration
  3. @ComponentScan
    我们可以直接用这三个注解也可以启动 springboot 应用,只是每次配置三个注解比较繁琐,所以直接用一个复合注解更方便些。然后仔细观察者三个注解,除了EnableAutoConfiguration 可能稍微陌生一点,其他两个注解使用得都很多

4.简单分析@Configuration

  1. Configuration这个注解大家应该有用过,它是JavaConfig形式的基于Spring IOC容器的配置类使用的一种注解。
  2. 因为SpringBoot本质上就是一个spring 应用,所以通过这个注解来加载IOC容器的配置是很正常的。所以在启动类 里面标注了@Configuration,意味着它其实也是一个 IoC 容器的配置类。
  3. 传统意义上的 spring 应用都是基于 xml 形式来配置 bean 的依赖关系。然后通过spring容器在启动的时候,把bean进行初始化并且,如果bean之间存在依赖关系,则分析这些已经在IoC容器中的bean根据依赖关系进行组装。
  4. 直到 Java5 中,引入了Annotations这个特性,Spring框架也紧随大流并且推出了基于 Java代码和Annotation元信息的依赖关系绑定描述的方式。也就是JavaConfig。
  5. 从spring3开始,spring就支持了两种bean的配置方式, 一种是基于xml文件方式、另一种就是JavaConfig 任何一个标注了@Configuration 的 Java 类定义都是一个 JavaConfig 配置类。而在这个配置类中,任何标注了 @Bean 的方法,它的返回值都会作为 Bean 定义注册到 Spring的IOC容器,方法名默认成为这个bean的id

5.简单分析 ComponentScan

  1. ComponentScan 这个注解是大家接触得最多的了,相当于 xml 配置文件中的context:component-scan
  2. 它的主要作用就是扫描指定路径下的标识了需要装配的类,自动装配到spring的Ioc容器中。 标识需要装配的类的形式主要是:@Component、 @Repository、@Service、@Controller这类的注解标识的类。
  3. ComponentScan 默认会扫描当前 package 下的的所有加 了相关注解标识的类到IoC容器中.

6.简单分析 EnableAutoConfiguration

  1. 仍然是在 spring3.1 版本中,提供了一系列的@Enable 开 头的注解,Enable主机应该是在JavaConfig框架上更进一 步的完善,用户在使用spring相关的框架是,避免配置大量的代码从而降低使用的难度

  2. 比如常见的一些 Enable 注解:EnableWebMvc,(这个注解引入了 MVC 框架在 Spring 应用中需要用到的所有 bean);

  3. 比如说@EnableScheduling,开启计划任务的支持;

  4. 找到EnableAutoConfiguration,我们可以看到每一个涉及 到Enable开头的注解,都会带有一个@Import的注解,@Import(AutoConfigurationImportSele ctor.class)

  5. Import 注解 import 注解是什么意思呢? 联想到 xml 形式下有一个 形式的注解,就明白它的作用了。 import就是把多个分来的容器配置合并在一个配置中。在 JavaConfig中所表达的意义是一样的。

7.深入分析 EnableAutoConfiguration

  1. EnableAutoConfiguration 的主要作用其实就是帮助 springboot 应用把所有符合条件的@Configuration 配置 都加载到当前SpringBoot创建并使用的IoC容器中。
  2. Enable注解不仅仅可以像前面演示的案例一样很简单的实 现多个 Configuration 的整合,还可以实现一些复杂的场景,
  3. 比如可以根据上下文来激活不同类型的 bean,@Import注解可以配置三种不同的class 1. 基于普通 bean 或者带有 @Configuration的bean进行诸如 2. 实现ImportSelector接口进行动态注入 3. 实现ImportBeanDefinitionRegistrar接口进行动态注入
  4. 它会通过import导入第三方提供的bean的配置类: Springboot @Enable*注解的工作原理ImportSelector接口 selectImports返回的数组(类的全类名)都会被纳入到 spring容器中。 那么可以猜想到这里的实现原理也一定是一样的,其实EnableAutoConfiguration会帮助 springboot应用把所有符合@Configuration配置都加载 到当前SpringBoot创建的IoC容器,而这里面借助了 Spring框架提供的一个工具类SpringFactoriesLoader的 支持。以及用到了Spring提供的条件注解 @Conditional,选择性的针对需要加载的bean进行条件过滤

8.简单分析SpringFactoriesLoader

为了给大家补一下基础,我在这里简单分析一下 SpringFactoriesLoader这个工具类的使用。它其实和java中的SPI机制的原理是一样的,不过它比SPI更好的点在于不会一次性加载所有的类,而是根据key进行加载。 首先,SpringFactoriesLoader 的作用是从 classpath/META-INF/spring.factories文件中,根据key来加载对应的类到spring IoC容器中。

9.深入理解条件过滤

  1. 会先扫描spring-autoconfiguration-metadata.properties 文件,最后在扫描spring.factories对应的类时,会结合前面的元数据进行过滤,
  2. 为什么要过滤呢? 原因是很多的@Configuration其实是依托于其他的框架来加载的, 如果当前的classpath环境下没有相关联的依赖,则意味着这些类没必要进行加载,
  3. 所以,通过这种条件过滤可以 有效的减少@configuration类的数量从而降低 SpringBoot的启动时间。

10.SpringBoot神器-Actuator

最基本的功能就是可以让你自定义一个类,加载到spring容器中,并且可以通过application.properties进行属性装配

最后展示一个小Demo

下篇文章就是实打实的springboot源码了