Spring Boot原始碼分析 - Configuration註解
@Configuration
註解指示一個類宣告一個或多個@Bean方法, 並且可以由Spring容器處理, 以在執行時為這些bean生成bean定義和服務請求.
使用ConfigurationClassParser
來對@Configuration
標註的類進行解析, 封裝成ConfigurationClass
例項. 具體的實現通過ConfigurationClassPostProcessor
來實現的.
ConfigurationClassPostProcessor
實現了BeanDefinitionRegistryPostProcessor
介面, 間接實現了BeanFactorPostProcessor
介面.
-
#postProcessBeanDefinitionRegistry()
: 註冊所有ConfigurationClass
中的BeanDefinition
, 包括@Bean
註解的方法,@ImporResource
引入的資源中定義的bean, 和@Import
註解引入的ImportBeanDefinitionRegistrar
中註冊的BeanDefinition
-
#postProcessBeanFactory()
: 在執行時以通過cglig
增強的類來替換ConfigurationClass
, 為服務bean請求做準備. 增強的實現是通過ConfigurationClassEnhancer
完成的.
插入一點,ConfigurationClassEnhancer
實現了直接使用bean註冊方法來獲取bean的操作, 提供了一個BeanMethodInterceptor
的內部類來實行.
@Configuration public class Config { @Bean public A a() { ... return a; } @Bean public B b() { b.setA(a()); ... return b; } }
Full ConfigurationClass VS Lite ConfigurationClass
先說區別: full的ConfigurationClass
會使用CGLIB進行增強.
檢視類ConfigurationClassUtils
, 其中有兩個方法#isFullConfigurationClass()
和#isLiteConfigurationClass()
.
方法的實現是去檢查BeanDefinition
中的ConfigurationClassPostProcessor.configurationClass
屬性, 是full
還是lite
.
這個屬性的值又來源於#checkConfigurationClassCandidate()
方法, 如果BeanDefinition
使用的是@Configuration
註解, 則為full
; 如果是@Component
,@ComponentScan
,@Import
或者@ImportResource
中的任何一種, 則為lite
. 如果是ConfigurationClass
, 則會繼續為其新增順序屬性.
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { ... if (isFullConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); } else if (isLiteConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); } else { return false; } // It's a full or lite configuration candidate... Let's determine the order value, if any. Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName()); if (orderAttributes != null) { beanDef.setAttribute(ORDER_ATTRIBUTE, orderAttributes.get(AnnotationUtils.VALUE)); } }