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自動配置開始沾點兒邊了

下面,重點來了,核心中的核心

終於寫完了,累死我了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM