简单详细的SpringBoot自动配置原理解析

简介: 上一篇文章我们介绍了SpringFactoriesLoader,之所以介绍SpringFactoriesLoader是因为我们这篇文章要介绍的SpringBoot的自动配置会用到SpringFactoriesLoader的知识。闲话少叙,让我们直入主题。

前言

上一篇文章我们介绍了SpringFactoriesLoader,之所以介绍SpringFactoriesLoader是因为我们这篇文章要介绍的SpringBoot的自动配置会用到SpringFactoriesLoader的知识。闲话少叙,让我们直入主题。

环境

spring-boot 1.5.8.RELEASE

从启动类开始

@SpringBootApplication
public class HelloworldDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloworldDemoApplication.class, args);
    }
}

如上,就是我们SpringBoot应用的启动类。让我们把眼光聚焦到@SpringBootApplication注解上面。这个注解是SpringBoot项目的主配置类。

@SpringBootApplication

//省略部分注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
  @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}

根据前几篇的介绍,我们可以知道@SpringBootApplication注解是一个组合注解。

@SpringBootConfiguration注解 表示这是SpringBoot的配置类,

@ComponentScan 开启组件扫描

@EnableAutoConfiguration这个注解的作用就是让SpringBoot开启自动配置。自动配置的奥秘全都在这里:

@EnableAutoConfiguration

//省略部分注解
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

如上我们可以看到EnableAutoConfiguration注解上有两个注解

1.@AutoConfigurationPackage 注解,

从字面意思上来看就是自动配置包。点进去可以看到就是⼀个 @Import 注解: @Import(AutoConfigurationPackages.Registrar.class) ,导⼊了⼀个

Registrar 的组件,这个注解的作用就是将主配置类(@SpringBootConfiguration标注的类)所在的包及其下面所有子包里面所有的组件扫描到IOC容器中。所以说,默认情况下主配置类所在包及其子包以外的组件,Spring IOC容器是扫描不到的。

2.@Import(AutoConfigurationImportSelector.class)

通过@Import导入了AutoConfigurationImportSelector类,而这个类的selectImports方法会通过SpringFactoriesLoader得到大量的配置类。而每个配置类则根据条件化配置类做出决策,以实现自动配置的功能。下面就让我们来看看selectImports方法。

AutoConfigurationImportSelector的selectImports方法

public String[] selectImports(AnnotationMetadata annotationMetadata) {
  //省略部分代码
  List<String> configurations = getCandidateConfigurations(annotationMetadata,
    attributes);
  return StringUtils.toStringArray(configurations);
  }
  protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
    AnnotationAttributes attributes) {
  List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
    getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
  return configurations;
  }
  protected Class<?> getSpringFactoriesLoaderFactoryClass() {
  return EnableAutoConfiguration.class;
  }

如上代码,自动配置核心的代码我都罗列出来了,最核心的就是loadFactoryNames方法,其主要有三步:

1.从classpath下获取所有META-INF/spring.factories这个文件下的信息。

2.将上面获取到的信息封装成Enumeration返回

3.遍历Enumeration,然后获取key为EnableAutoConfiguration下的所有值。

META-INF/spring.factories 这类⽂件是什么就不懵了。当然在很多第三⽅依赖中

都会有这个⽂件,⼀般每导⼊⼀个第三⽅的依赖,除了本⾝的jar包以外,还会有⼀个 xxx-spring-boot-autoConfigure,这个就

是第三⽅依赖⾃⼰编写的⾃动配置类。我们现在就以 spring-boot-autocongigure 这个依赖来说下,其下面的META-INF/spring.factories文件。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\

配置类注册到IOC容器的流程图

然后就是实例化这些配置类注册到IOC容器中。流程如下:



以DataSourceAutoConfiguration进行说明

通过上面的方式,所有的自动配置类都被导进主配置类中,但是这么多的配置类,明显有很多我们平常是没有使用到的,没必要全部生效,下面我们以DataSourceAutoConfiguration配置类为例来看一下自动配置类是如何工作的:

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
}

@Configuration 注解表明了DataSourceAutoConfiguration类是一个JavaConfig配置类。@ConditionalOnClass只有当classpath中存在DataSource类或者EmbeddedDatabaseType类时才启动这个配置。@EnableConfigurationProperties这个注解的作用是将将DataSource类注入到IOC容器中。@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })是要导入额外的配置DataSourcePoolMetadataProvidersConfiguration。

DataSourceProperties 类

下面我们就来一个个看一下:首先是DataSourceProperties类:

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
  implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
  private ClassLoader classLoader;
  private Environment environment;
  private String name = "testdb";
  private boolean generateUniqueName;
  private Class<? extends DataSource> type;
  private String driverClassName;
  private String url;
  }

DataSourceProperties 通过@ConfigurationProperties注解将配置文件的前缀为(spring.datasource)的配置信息与自身的属性绑定。所有在配置⽂件中能配置的属性都是在 xxxProperties 类中封装着;配置⽂件能配置什么就可以参照某个功能对应的这个属性

类。

DataSourcePoolMetadataProvidersConfiguration 类

@Configuration
public class DataSourcePoolMetadataProvidersConfiguration {
  @Configuration
  @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
  static class TomcatDataSourcePoolMetadataProviderConfiguration {
  }
  @Configuration
  @ConditionalOnClass(HikariDataSource.class)
  static class HikariPoolDataSourceMetadataProviderConfiguration {

DataSourcePoolMetadataProvidersConfiguration 类是数据库连接池提供者的一个配置类。即classpath中存在org.apache.tomcat.jdbc.pool.DataSource.class则使⽤tomcat-jdbc连接池,如果classpath中存在 HikariDataSource.class则使⽤ Hikari连接池,如果存在org.apache.commons.dbcp.BasicDataSource.class则启用dbcp 连接池。

总结

1.SpringBoot启动时会扫描项目所依赖的JAR包,寻找包含spring.factories文件的JAR包。

2.根据spring.factories配置加载EnableAutoConfiguration

其中给容器中自动配置添加组件的时候,会从propeties类中获取配置文件中指定这些属性的值。xxxAutoConfiguration:⾃动配置类给容器中添加组件。xxxProperties:封装配置⽂件中相关属性。

3.根据@Conditional注解的条件,进行自动配置并将Bean注入Spring容器


相关文章
|
10小时前
|
安全 Java 开发者
深入理解Spring Boot配置绑定及其实战应用
【4月更文挑战第10天】本文详细探讨了Spring Boot中配置绑定的核心概念,并结合实战示例,展示了如何在项目中有效地使用这些技术来管理和绑定配置属性。
11 1
|
10小时前
|
机器学习/深度学习 存储 算法
卷积神经网络(CNN)的数学原理解析
卷积神经网络(CNN)的数学原理解析
5 1
卷积神经网络(CNN)的数学原理解析
|
10小时前
|
XML Java 开发者
springboot 启动原理、启动过程、启动机制的介绍
【5月更文挑战第13天】Spring Boot 是一种基于 Java 的框架,用于创建独立的、生产级别的 Spring 应用程序。它的主要目标是简化 Spring 应用的初始搭建和开发过程,同时提供一系列大型项目常见的非功能性特征(如嵌入式服务器、安全性、度量、健康检查和外部化配置)。
17 3
|
10小时前
|
XML JavaScript 数据格式
Beautiful Soup 库的工作原理基于解析器和 DOM(文档对象模型)树的概念
【5月更文挑战第10天】Beautiful Soup 使用解析器(如 html.parser, lxml, html5lib)解析HTML/XML文档,构建DOM树。它提供方法查询和操作DOM,如find(), find_all()查找元素,get_text(), get()提取信息。还能修改DOM,添加、修改或删除元素,并通过prettify()输出格式化字符串。它是处理网页数据的利器,尤其在处理不规则结构时。
23 2
|
10小时前
|
机器学习/深度学习 人工智能 数据可视化
号称能打败MLP的KAN到底行不行?数学核心原理全面解析
Kolmogorov-Arnold Networks (KANs) 是一种新型神经网络架构,挑战了多层感知器(mlp)的基础,通过在权重而非节点上使用可学习的激活函数(如b样条),提高了准确性和可解释性。KANs利用Kolmogorov-Arnold表示定理,将复杂函数分解为简单函数的组合,简化了神经网络的近似过程。与mlp相比,KAN在参数量较少的情况下能达到类似或更好的性能,并能直观地可视化,增强了模型的可解释性。尽管仍需更多研究验证其优势,KAN为深度学习领域带来了新的思路。
93 5
|
10小时前
|
敏捷开发 测试技术 持续交付
极限编程(XP)原理与技巧:深入解析与实践
【5月更文挑战第8天】极限编程(XP)是一种敏捷开发方法,注重快速反馈、迭代开发和简单设计,以提高软件质量和项目灵活性。关键原则包括客户合作、集体代码所有权、持续集成等。实践中,使用故事卡片描述需求,遵循编程约定,实行TDD,持续重构,结对编程,并定期举行迭代会议。通过理解和应用XP,团队能提升效率,应对变化。
|
10小时前
|
Java 文件存储 Spring
【springboot】logback配置
【springboot】logback配置
19 1
|
10小时前
|
缓存 自然语言处理 JavaScript
万字长文深度解析JDK序列化原理及Fury高度兼容的极致性能实现
Fury是一个基于JIT动态编译的高性能多语言原生序列化框架,支持Java/Python/Golang/C++/JavaScript等语言,提供全自动的对象多语言/跨语言序列化能力,以及相比于别的框架最高20~200倍的性能。
163702 0
|
10小时前
|
缓存 测试技术 Android开发
深入了解Appium:Capability 高级配置技巧解析
Appium 提供多种进阶配置项以优化自动化测试,如 deviceName 作为设备别名,udid 确保选择特定设备,newCommandTimeout 设置超时时间,PRINT_PAGE_SOURCE_ON_FIND_FAILURE 在错误时打印页面源,以及测试策略中的 noReset、shouldTerminateApp 和 forceAppLaunch 控制应用状态和重启。这些配置可提升测试效率和准确性。
17 2
|
10小时前
|
存储 弹性计算 固态存储
阿里云服务器配置选择指南,2024年全解析
阿里云服务器配置选择涉及CPU、内存、带宽和磁盘。个人开发者或中小企业推荐使用轻量应用服务器或ECS经济型实例,如2核2G3M配置,适合网站和轻量应用。企业用户则应选择企业级独享型ECS,如计算型c7、通用型g7,至少2核4G起,带宽建议5M,系统盘考虑SSD云盘或ESSD云盘以保证性能。阿里云提供了多种实例类型和配置,用户需根据实际需求进行选择。

推荐镜像

更多