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

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

1.  @EnableAutoConfiguration

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

然后,去重

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

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

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

删除所有需要排除的

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

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

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

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

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

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

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

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

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

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

首先看createApplicationContext()

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

看看AnnotationConfigServletWebServerApplicationContext有多复杂

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

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

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

下面重点看一下AnnotatedBeanDefinitionReader

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

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

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

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

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

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

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

CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 对应的是 ConfigurationClassPostProcessor

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

接下来,看prepareContext()

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

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

Spring Boot 自动配置 源码分析_Spring Boot_27 Spring Boot 自动配置 源码分析_Spring Boot_28

重点看SharedMetadataReaderFactoryContextInitializer

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

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

最后,再来看refreshContext()

调用是Spring的refresh()

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

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

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

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

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

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

好,记住这一点

继续看PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()

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

好,看CachingMetadataReaderFactoryPostProcessor#postProcessBeanDefinitionRegistry()

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

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

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

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

得到ConfigurationClassPostProcessor

接下来,调用postProcessBeanDefinitionRegistry

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

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

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

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

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

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

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

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

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

终于写完了,累死我了