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自動配置開始沾點兒邊了
下面,重點來了,核心中的核心
終于寫完了,累死我了