Spring Boot 自动配置 源码分析

时间:2022-02-02 16:20:16

Spring Boot 最大的特点(亮点)就是自动配置 AutoConfiguration

下面,先说一下 @EnableAutoConfiguration ,然后再看源代码,到底自动配置是怎么配置的

1.  @EnableAutoConfiguration

Spring Boot 自动配置 源码分析

@SpringBootApplication是一个复合注解,本节我们重点关注 @EnableAutoConfiguration

Spring Boot 自动配置 源码分析

自动配置类是常规的Spring @Configuration bean。它们使用SpringFactoriesLoader机制定位。通常,自动配置bean是@Conditional Bean(最经常使用@ConditionalOnClass和@ConditionalOnMissingBean注解)

在@EnableAutoConfiguration注解上有一个@Import注解

@Import这个注解表明要导入的一个或多个组件类,通常是@Configuration类。

@Import注解提供与Spring XML中的<import />元素等效的功能。允许导入@Configuration类,ImportSelector和ImportBeanDefinitionRegistrar实现以及常规组件类。

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

根据导入的@Configuration类的AnnotationMetadata,返回AutoConfigurationImportSelector.AutoConfigurationEntry。

方法的参数AnnotationMetadata代表配置类上的注解元数据,方法的返回值是应该被导入的自动配置类

首先,获取配置类上的注解的属性

Spring Boot 自动配置 源码分析

又是熟悉的方法:SpringFactoriesLoader.loadFactoryNames()

Spring Boot 自动配置 源码分析

在所有 META-INF/spring.factories 文件中查找 org.springframework.boot.autoconfigure.EnableAutoConfiguration

Spring Boot 自动配置 源码分析

然后,去重

Spring Boot 自动配置 源码分析

然后,再排除一些,根据注解属性中明确指定的exclude

Spring Boot 自动配置 源码分析

删除所有需要排除的

然后,过滤掉一些不需要的

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

根据对所有的需要自动配置的类应用那三个过滤器

最终剩下的就是真正需要导入的,或者说真正需要自动配置的

在众多需要自动配置的类中,我们挑一个熟悉的来看一下,就挑org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

Spring Boot 自动配置 源码分析

看这注解,当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 自动配置源码分析

Spring Boot 自动配置 源码分析

又来到了熟悉的SpringApplication.run()方法这里,这一次,重点看其中的三步:createApplicationContext()、prepareContext() 和 refreshContext()

首先看createApplicationContext()

Spring Boot 自动配置 源码分析

看看AnnotationConfigServletWebServerApplicationContext有多复杂

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

创建了两个BeanDefinition分别是AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner,它们都是用来查找并加载Bean定义的,只是方式不同而已

下面重点看一下AnnotatedBeanDefinitionReader

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

(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()

我们单独把这段拿出来再看一下

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

如果没有这个BeanDefinition的时候就添加一个

CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 对应的是 ConfigurationClassPostProcessor

先记住这一点,后面会用到

接下来,看prepareContext()

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析 Spring Boot 自动配置 源码分析

重点看SharedMetadataReaderFactoryContextInitializer

Spring Boot 自动配置 源码分析

好,记住这一点,此处添加了一个BeanFactoryPostProcessor,它是一个CachingMetadataReaderFactoryPostProcessor

最后,再来看refreshContext()

调用是Spring的refresh()

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

重点看 invokeBeanFactoryPostProcessors 调用所有已注册的BeanPostProcessor

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

这里,调用getBeanFactoryPostProcessors()返回的BeanFactoryPostProcessors中有CachingMetadataReaderFactoryPostProcessor

好,记住这一点

继续看PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()

Spring Boot 自动配置 源码分析

好,看CachingMetadataReaderFactoryPostProcessor#postProcessBeanDefinitionRegistry()

Spring Boot 自动配置 源码分析

又看到了熟悉的AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,我们知道它是ConfigurationClassPostProcessor

回到PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()继续往下看

Spring Boot 自动配置 源码分析

得到ConfigurationClassPostProcessor

接下来,调用postProcessBeanDefinitionRegistry

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

方法太长,就不截全图了,总之就是找到配置类,开始解析配置类了,只看重点

到这里终于和我们前面讲的@EnableAutoConfiguration自动配置开始沾点儿边了

Spring Boot 自动配置 源码分析

Spring Boot 自动配置 源码分析

下面,重点来了,核心中的核心

Spring Boot 自动配置 源码分析

终于写完了,累死我了