Spring Boot 自动配置 源码分析
Spring Boot 最大的特点(亮点)就是自动配置 AutoConfiguration
下面,先说一下 @EnableAutoConfiguration ,然后再看源代码,到底自动配置是怎么配置的
1. @EnableAutoConfiguration
@SpringBootApplication是一个复合注解,本节我们重点关注 @EnableAutoConfiguration
自动配置类是常规的Spring @Configuration bean。它们使用SpringFactoriesLoader机制定位。通常,自动配置bean是@Conditional Bean(最经常使用@ConditionalOnClass和@ConditionalOnMissingBean注解)
在@EnableAutoConfiguration注解上有一个@Import注解
@Import这个注解表明要导入的一个或多个组件类,通常是@Configuration类。
@Import注解提供与Spring XML中的<import />元素等效的功能。允许导入@Configuration类,ImportSelector和ImportBeanDefinitionRegistrar实现以及常规组件类。
根据导入的@Configuration类的AnnotationMetadata,返回AutoConfigurationImportSelector.AutoConfigurationEntry。
方法的参数AnnotationMetadata代表配置类上的注解元数据,方法的返回值是应该被导入的自动配置类
首先,获取配置类上的注解的属性
又是熟悉的方法:SpringFactoriesLoader.loadFactoryNames()
在所有 META-INF/spring.factories 文件中查找 org.springframework.boot.autoconfigure.EnableAutoConfiguration
然后,去重
然后,再排除一些,根据注解属性中明确指定的exclude
删除所有需要排除的
然后,过滤掉一些不需要的
根据对所有的需要自动配置的类应用那三个过滤器
最终剩下的就是真正需要导入的,或者说真正需要自动配置的
在众多需要自动配置的类中,我们挑一个熟悉的来看一下,就挑org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
看这注解,当classpath中有RedisOperations时才会自动配置该类,当有RedisConnectionFactory且没有redisTemplate时才会创建一个redisTemplate,同理,有RedisConnectionFactory且没有stringRedisTemplate时才会创建一个stringRedisTemplate
回顾一下
1、在所有 META-INF/spring.factories 文件中查找 org.springframework.boot.autoconfigure.EnableAutoConfiguration,返回一个List<String>
2、对上一步返回的List去重
3、根据注解exclude属性排除List中的一些元素
4、根据AutoConfigurationImportFilter过滤掉一些不需要自动配置的元素
5、讲过以上四步,List中剩下的元素就是最终需要自动配置的元素(类)
至此,只是筛选出了哪些类需要自动配置,但还没有真正装配(实例化),真正实例化Bean是在Spring Boot启动时刷新ApplicationContext时做的
注解只是个标记,是给反射用的,有注解必然有处理它的类
接下来,分析源码,看看究竟什么时候开始真正自动装配
2. Spring Boot 自动配置源码分析
又来到了熟悉的SpringApplication.run()方法这里,这一次,重点看其中的三步:createApplicationContext()、prepareContext() 和 refreshContext()
首先看createApplicationContext()
看看AnnotationConfigServletWebServerApplicationContext有多复杂
创建了两个BeanDefinition分别是AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner,它们都是用来查找并加载Bean定义的,只是方式不同而已
下面重点看一下AnnotatedBeanDefinitionReader
(PS:其实,这里注册了很多BeanPostProcessor,有处理Autowired的AutowiredAnnotationBeanPostProcessor,由于本节主要讲自动配置的,所以我们重点关注ConfigurationClassPostProcessor)
先做个笔记:
1、ApplicationContext 是 AnnotationConfigServletWebServerApplicationContext
2、构造了一个AnnotatedBeanDefinitionReader,大家要明白BeanDefinitionReader是用来加载Bean定义的
3、把这个AnnotatedBeanDefinitionReader注册(关联)到该ApplicationContext
4、在构造AnnotatedBeanDefinitionReader的时候注册了很多Processors
可见AnnotatedBeanDefinitionReader真的是相当相当重要,而重中之重是org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors()
我们单独把这段拿出来再看一下
如果没有这个BeanDefinition的时候就添加一个
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 对应的是 ConfigurationClassPostProcessor
先记住这一点,后面会用到
接下来,看prepareContext()
重点看SharedMetadataReaderFactoryContextInitializer
好,记住这一点,此处添加了一个BeanFactoryPostProcessor,它是一个CachingMetadataReaderFactoryPostProcessor
最后,再来看refreshContext()
调用是Spring的refresh()
重点看 invokeBeanFactoryPostProcessors 调用所有已注册的BeanPostProcessor
这里,调用getBeanFactoryPostProcessors()返回的BeanFactoryPostProcessors中有CachingMetadataReaderFactoryPostProcessor
好,记住这一点
继续看PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
好,看CachingMetadataReaderFactoryPostProcessor#postProcessBeanDefinitionRegistry()
又看到了熟悉的AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,我们知道它是ConfigurationClassPostProcessor
回到PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()继续往下看
得到ConfigurationClassPostProcessor
接下来,调用postProcessBeanDefinitionRegistry
方法太长,就不截全图了,总之就是找到配置类,开始解析配置类了,只看重点
到这里终于和我们前面讲的@EnableAutoConfiguration自动配置开始沾点儿边了
下面,重点来了,核心中的核心
终于写完了,累死我了
Spring Boot 自动配置 源码分析的更多相关文章
- Spring Boot自动配置源码解析(基于Spring Boot 2.0.2.RELEASE)
在Spring Boot官方介绍中,首一段话是这样的(如下图).我们可以大概了解到其所表达的含义:我们可以利用Spring Boot写很少的配置来创建一个非常方便的基于Spring整合第三方类库的单体 ...
- spring boot 2.0 源码分析(一)
在学习spring boot 2.0源码之前,我们先利用spring initializr快速地创建一个基本的简单的示例: 1.先从创建示例中的main函数开始读起: package com.exam ...
- spring boot 2.0 源码分析(四)
在上一章的源码分析里,我们知道了spring boot 2.0中的环境是如何区分普通环境和web环境的,以及如何准备运行时环境和应用上下文的,今天我们继续分析一下run函数接下来又做了那些事情.先把r ...
- spring boot 2.0 源码分析(二)
在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数. 先把这段run函数的代码贴出来: /** * Run the ...
- spring boot 2.0 源码分析(三)
通过上一章的源码分析,我们知道了spring boot里面的listeners到底是什么(META-INF/spring.factories定义的资源的实例),以及它是创建和启动的,今天我们继续深入分 ...
- spring boot 2.0 源码分析(五)
在上一篇文章中我们详细分析了spring boot是如何准备上下文环境的,今天我们来看一下run函数剩余的内容.还是先把run函数贴出来: /** * Run the Spring applicati ...
- Springboot 系列(三)Spring Boot 自动配置原理
注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring ...
- SpringBoot自动配置源码调试
之前对SpringBoot的自动配置原理进行了较为详细的介绍(https://www.cnblogs.com/stm32stm32/p/10560933.html),接下来就对自动配置进行源码调试,探 ...
- Spring Boot自动配置与Spring 条件化配置
SpringBoot自动配置 SpringBoot的自动配置是一个运行时(应用程序启动时)的过程,简化开发时间,无需浪费时间讨论具体的Spring配置,只需考虑如何利用SpringBoot的自动配置即 ...
随机推荐
- kubernetes进阶(五)dashboard--WEB管理
dashboard是k8s的可视化管理平台,是三种管理k8s集群方法之一 首先下载镜像上传到我们的私有仓库中:hdss7-200 # docker pull k8scn/kubernetes-dash ...
- 根据直方图 histogram 进行简单的图像检索
https://github.com/TouwaErioH/Machine-Learning/tree/master/image%20identification/Histogram%20retrie ...
- Win7环境下mysql报错1045:Access denied for user root@localhost错误解决方法
产生场景:在涉及到连接数据库操作的时候,会报1045:Access denied for user root@localhost. 比如:本地建立的数据库连接不上,在IDEA等开发工具中使用反向生成. ...
- 记一次FreeRTOS错误配置导致无法进入临界区
最近项目用到FreeRTOS,在实际调试中发现我自己的一段代码本来好用的(在无RTOS的情况下),但是当我在带RTOS的情况下把代码放到一个单独的任务中运行时我发现本来好用的代码莫名其妙的出现问题,有 ...
- 析构函数 & 构造函数
析构函数 & 构造函数 C++ 析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数. 析构函数往往用来做"清理 ...
- Axios & POST & application/x-www-form-urlencoded
Axios & POST & application/x-www-form-urlencoded application/x-www-form-urlencoded https://g ...
- 【C#】反射的用法及效率对比
反射实例化类 public class Person { public string Name { get; set; } public Person(string name) { this.Name ...
- django学习-21.优化表数据的标题展示
目录结构 1.前言 2.表数据的标题默认展示的数据格式是[模型类名 object(主键名)]的相关信息 3.优化表数据的标题展示的数据格式是[改成我们想要展示的数据格式]的相关完整操作步骤 3.1.第 ...
- 那些容易犯错的c++保留字
本文首发 | 公众号:lunvey 目前正在学习vc++6.0开发,而这里面使用的是c++98标准. 保留字,也称关键字,是指在变量.函数.类中不得重新声明的名称. c++98中大致有48个保留字,这 ...
- CentOS7安装ElasticSearch7.9.2
1:下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.2-linux-x86_64.tar. ...