【框架源码】SpringBoot核心源码解读之自动配置源码分析

简介: 【框架源码】SpringBoot核心源码解读之自动配置源码分析

SpringBoot流行之前,程序员大多是用SSM框架整合来进行WEB后端开发。这种方式非常麻烦,需要手动引入大量的包,还要配置很多XML文件,光是搭建环境就需要很久。

基于这种的SSM中xml配置的繁琐,后来衍生出SpringBoot。SpringBoot中的自动装载,大大简化了开发者对于配置的相关信息。

问题:什么是SpringBoot自动配置

  • 当spring容器启动后,一些自动配置类通过@Conditional注解自动装配的IOC容器中
  • 不需要手动去注入,简化了开发,省去了繁琐的配置
  • 自动配置的相关工作就在 @SpringBootApplication这个注解上

我们来看一下@SpringBootApplication这个注解。

@Target({ElementType.TYPE})  //注解的作用范围,用在类,接口,注解等上面
@Retention(RetentionPolicy.RUNTIME) //注解生命周期,runtime,保留在运行时期
@Documented //可以被文档化
@Inherited //可以被子类继承
@SpringBootConfiguration  //里面是@Configuration属于配置类
@EnableAutoConfiguration  //启动自动配置功能
//配置扫描包
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication

@SpringBootApplication 是一个复合注解,由几个核心的注解组成。

  • @SpringBootConfiguration
  • 里面是 @Configuration,代表是一个配置类,说明主程序类也是一个配置类
  • @EnableAutoConfiguration
  • @AutoConfigurationPackage 将指定的一个包下的所有组件导入到容器当中
  • 在@AutoConfigurationPackage 注解中存在一个 @Import({Registrar.class}) 注解,自动配置包就是通过这个完成的。
  • @ComponentScan
  • 指定扫描哪些组件,默认是扫描主程序所在的包以及其子包
  • 它的核心在于@EnableAutoConfiguration这个注解,这里面是加载自动配置的类信息。

@EnableAutoConfiguration注解核心内容

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //自动配置包
@Import(AutoConfigurationImportSelector.class) //通过import导入满足条件的bean,并加载到spring的ioc容器里面
public @interface EnableAutoConfiguration 

@AutoConfigurationPackage注解核心内容

  • Registrar的作用是扫描包,默认是把主类所在的包和子包里面全部类扫描进容器里面
  • 所以为什么开发springboot项目需要把主类放到最外层目录,不然就对的注解类就找不到
@Import(AutoConfigurationPackages.Registrar.class) //把Registrar导入到spring容器里面

核心逻辑为这段逻辑,一会我们会断点进行调试。

    //获取主程序所在的目录为位置,metadata是元注解信息
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata,
        BeanDefinitionRegistry registry) {
      register(registry, new PackageImport(metadata).getPackageName());
    }

下面,我们来看一下@Import(AutoConfigurationImportSelector.class)这个里面都做了哪些操作。其核心就是通过import导入满足条件的bean, 把springboot应用里面符合@Configuration的类,加载到spring的ioc容器里面

  //用于实现动态注册Bean的功能,【批量】导入对象到容器里,根据条件动态地选择需要注册的Bean,并加入Spring容器
  //实现ImportSelector接口,这个接口的selectImports方法会返回一个String数组,数组中的值就是要添加的组件的全类名
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
      return NO_IMPORTS;
    }
    //加载元数据信息
    AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
        .loadMetadata(this.beanClassLoader);
    //获取需要自动装载的类的信息
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
        autoConfigurationMetadata, annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
  }

ok,我们再来看一下getAutoConfigurationEntry()这个方法的逻辑。这个方法主要是根据指定的注解元数据获取自动配置的条目。

protected AutoConfigurationEntry getAutoConfigurationEntry(
      AutoConfigurationMetadata autoConfigurationMetadata,
      AnnotationMetadata annotationMetadata) {
    //判断是否启用了自动配置
    if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
    }
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    //获取候选自动配置类列表
    List<String> configurations = getCandidateConfigurations(annotationMetadata,
        attributes);
    //去除重复的自动配置类
    configurations = removeDuplicates(configurations);
    //获取需要排除的自动配置类列表
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    //检查是否存在需要排除的自动配置类
    checkExcludedClasses(configurations, exclusions);
    //将需要排除的类从自动配置类列表中移除
    configurations.removeAll(exclusions);
    //获取配置类过滤器,对候选自动配置类列表进行过滤
    configurations = filter(configurations, autoConfigurationMetadata);
    //触发自动配置导入事件,并返回一个新的自动配置条目
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
  }

我们来看看getCandidateConfigurations()这里面核心逻辑就是去META-INF/spring.factories这个文件中去拉取全部的配置信息。

  protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
      AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
    Assert.notEmpty(configurations,
        "No auto configuration classes found in META-INF/spring.factories. If you "
            + "are using a custom packaging, make sure that file is correct.");
    return configurations;
  }
  public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

好的,接下来我们来调试走下源码流程。

a1f8bffd3e694ef3a37988a696dc9a28.jpg

987c568e8fb74e5d89d7b7aa24ca3c46.jpg

0262e2ac3d3f4bf196a98d85b29d1885.jpg

32e9efa28ee5450f82ca0f46d5c2a752.jpg


9fe6a8b9fcba4a8296584e3b54f1c8a3.jpg

2daf7353fbbe44a7bbbd069f3e7b3ec9.jpg


49d6b3f546f74d5bbe6ebccbd652033e.jpg


ca5fa536f36449209b0b840a7c48383e.jpg

0b8c6fc7fe9f45df8f5def188fab3c6b.jpg

c6659135d6a042e5a5496e46a6e14bbe.jpg

2400ac1c88f342efb4b2558a1967ccb8.jpg

4e027a709d5549bfa75f876683cc5e3b.jpg

ok,我们来总结一下,SpringBoot自动装载的全流程。


首先,加载一下元数据信息

获取需要自动装载的类的信息

判断是否启用了自动配置

获取候选自动配置类列表

获取需要排除的自动配置类列表

检查是否存在需要排除的自动配置类

将需要排除的类从自动配置类列表中移除

获取配置类过滤器,对候选自动配置类列表进行过滤

触发自动配置导入事件,并返回一个新的自动配置条目

注册Bean的定义列表


相关文章
|
14天前
|
缓存 前端开发 Java
【Java】仓库管理系统 SpringBoot+LayUI+DTree(源码)【独一无二】
【Java】仓库管理系统 SpringBoot+LayUI+DTree(源码)【独一无二】
|
15天前
|
Java 调度 Spring
SpringBoot实现多线程定时任务动态定时任务配置文件配置定时任务
SpringBoot实现多线程定时任务动态定时任务配置文件配置定时任务
38 0
|
26天前
|
SQL Java 数据库连接
springboot中配置mybatis别名该怎么写?
springboot中配置mybatis别名该怎么写?
19 0
|
1天前
|
消息中间件 运维 供应链
springboot区域云HIS医院信息综合管理平台源码
云HIS系统分为两个大的系统,一个是基层卫生健康云综合管理系统,另一个是基层卫生健康云业务系统。基层卫生健康云综合管理系统由运营商、开发商和监管机构使用,用来进行运营管理、运维管理和综合监管。基层卫生健康云业务系统由基层医院使用,用来支撑医院各类业务运转。
15 2
|
4天前
|
Java Shell 测试技术
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
16 0
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
|
8天前
|
Java 容器
SpringBoot使用配置注解开启自动配置功能&整合spring-boot-configuration-processor
SpringBoot使用配置注解开启自动配置功能&整合spring-boot-configuration-processor
12 0
|
13天前
|
JavaScript Java 关系型数据库
基于 java + Springboot + vue +mysql 大学生实习管理系统(含源码)
本文档介绍了基于Springboot的实习管理系统的设计与实现。系统采用B/S架构,旨在解决实习管理中的人工管理问题,提高效率。系统特点包括对用户输入的验证和数据安全性保障。功能涵盖首页、个人中心、班级管理、学生管理、教师管理、实习单位管理、实习作业管理、教师评分管理、单位成绩管理和系统管理等。用户分为管理员、教师和学生,各自有不同的操作权限。
|
15天前
|
Java 应用服务中间件
Springboot启动的时候初始化的线程池默认配置tomcat
Springboot启动的时候初始化的线程池默认配置tomcat
12 1
|
15天前
|
Java
SpringBoot配置图片访问404SpringBoot配置图片访问路径springboot如何访问图片
SpringBoot配置图片访问404SpringBoot配置图片访问路径springboot如何访问图片
6 0
|
27天前
|
运维 监控 Java
springboot基层医院综合HIS信息管理系统源码 医生工作站、护士工作站
病例质控:医生个人质控、病历控制、缺陷监控、质控设置、病历查询、统计分析
25 0
springboot基层医院综合HIS信息管理系统源码 医生工作站、护士工作站