【框架源码】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的定义列表


相关文章
|
19天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
4天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
18 0
|
8天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
19 2
 SpringBoot入门(7)- 配置热部署devtools工具
|
7天前
|
Java 数据库连接
SpringBoot配置多数据源实战
第四届光学与机器视觉国际学术会议(ICOMV 2025) 2025 4th International Conference on Optics and Machine Vision
33 8
|
23天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
42 1
Spring 框架:Java 开发者的春天
|
4天前
|
Java 数据库连接 数据库
springboot启动配置文件-bootstrap.yml常用基本配置
以上是一些常用的基本配置项,在实际应用中可能会根据需求有所变化。通过合理配置 `bootstrap.yml`文件,可以确保应用程序在启动阶段加载正确的配置,并顺利启动运行。
10 2
|
15天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
16天前
|
Java Spring 容器
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
43 3
|
14天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
65 1
|
23天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。