createBean解析
spring當中單例bean的建立原理,其中涉及到了非常多階段及各種處理器的調用
啟動代碼
通過注解配置類AppConfig啟動一個容器,其中添加了一個自定義的beanFactoryPostProcessor, 注意:這個類是直接添加到beanFactoryPostProcessors中的,沒有被spring當成bean放到單例map中
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.addBeanFactoryPostProcessor(new CustomBeanFactoryPostProcessor());
ac.register(AppConfig.class);
ac.refresh();
new AnnotationConfigApplicationContext
完成的初始化:
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
初始化了AnnotatedBeanDefinitionReader又完成了spring内置幾大處理器的注冊
生成了對應RootBeanDefinition,并通過registry加到了map中
beanName | beanClass |
---|---|
org.springframework.context.annotation.internalConfigurationAnnotationProcessor | ConfigurationClassPostProcessor |
org.springframework.context.annotation.internalAutowiredAnnotationProcessor | AutowiredAnnotationBeanPostProcessor |
org.springframework.context.annotation.internalCommonAnnotationProcessor | CommonAnnotationBeanPostProcessor |
org.springframework.context.event.internalEventListenerProcessor | EventListenerMethodProcessor |
org.springframework.context.event.internalEventListenerFactory | DefaultEventListenerFactory |
register 注冊了自己的配置類
通過構造ApplicationContext時産生的reader解讀這個注解類,并把配置類當成一個AnnotatedGenericBeanDefinition放入map中等待後續執行個體化。中間處理了一些common的注解資訊并填沖到bd裡,比如@Lazy,@Primary,@Role,@DependsOn, @Description等
refresh 方法解析
refresh方法中是個模闆方法,裡面定義了很多階段操作,其中主要分析以下幾個
invokeBeanFactoryPostProcessors(beanFactory)
主要完成了下面一個操作,其中getBeanFactoryPostProcessors()拿的就是我們手動add進去的那個processor清單,是以目前隻有一個
第一步:優先周遊這個list,并加入到對應清單中
BeanDefinitionRegistryPostProcessor -> List<BeanDefinitionRegistryPostProcessor> registryProcessors
BeanFactoryPostProcessor -> List<BeanFactoryPostProcessor> regularPostProcessors
注意 這裡對BeanDefinitionRegistryPostProcessor 會先觸發 postProcessBeanDefinitionRegistry 因為可能在這個方法裡面需要引入額外的banFactoryPostProcessor類,等待下一步執行
接下來開始按優先級順序查找并執行beanFactory中目前的registryPostProcessor
此刻bd map中已經有了如下幾個内置類:5個内置+1個自己注解類
第二步:從beanFactory中拿出所有PriorityOrdered BeanDefinitionRegistryPostProcessor的beanName
此時滿足條件的隻有
ConfigurationClassPostProcessor
, beanFactory.getBean會将它産生出來并放到緩存中
并執行 處理器對registry的實作邏輯,這裡的配置處理器會将目前所有的bd拿出來判斷解析,構造所有需要産生的bd并存放起來 (執行了 )
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
step -> ConfigurationClassPostProcessor
processConfigBeanDefinitions
判斷beanDefinition中屬性org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass是否有值(不成立,目前還沒被設定過值)
然後checkConfigurationClassCandidate(看是不是候選的配置類)
- 如果是配置類,産生的bd是AnnotatedGenericBean,會滿足第一個條件設定好metaData
- 如果這個bean是自己注冊的,有可能是AbstractBeanDefinition類型,那麼再看是不是BeanFactoryPostProcessor,BeanPostProcessor,AopInfrastructureBean,EventListenerFactory等特殊類型,不是的化也設定metadata否則直接結束
拿出Configuration注解的屬性資訊,允許代理bean方法情況下,設定注解屬性為full(就是這個時候才添加了标記,對應前面第一次拿是空);如果沒有@Configuration,拿出來的config是null,但是目前有@Bean method,else if中标記為lite
然後用ConfigurationClassParser 去解析配置類的相關資訊,包括Component, PropertySources,ComponentScans,ComponentScan, @Import, ImportResource,
等,最終存在ConfigurationClass包裝類中
private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
new LinkedHashMap<>();
private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
new LinkedHashMap<>();
final Set<String> skippedBeanMethods = new HashSet<>();
接着ConfigurationClassBeanDefinitionReader 去加載這些資訊loadBeanDefinitions到bd map中
再通過registry直接往容器中的singletonObjects中注冊一個處理Import注解的處理類 ,沒有走beanDefinition->create邏輯
beanName | beanClass |
---|---|
org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry | org.springframework.context.annotation.ConfigurationClassParser.ImportStack |
完成所有import和其他相關注解資訊的處理後,相關需要被掃面加載的bd都已經被存放到beanFactory中的bd map中等待被建立了
第三步 再從容器中找出所有beanFactoryPostProcessor (還是隻有一個被執行過的configuration處理類)
如果未被執行過或不是Order優先級的,跳過
第四步 從容器中找出所有beanFactoryPostProcessor,不對接口限制
處理所有未處理的process方法,并繼續循環擷取防止目前又産生新的處理器
第五步 對所有後置處理器(包括特殊的registry和普通beanFactoryPostprocessor)調用接口方法
postProcessBeanFactory
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
ConfigurationClassPostProcessor postProcessBeanFactory
會對目前所有bd找出可能的注解類,隻對full屬性的類進行如下邏輯
-
CGLIB 增強@Configuration的類 , enhanceConfigurationClasses
對标記為full的進行ConfigurationClassEnhancer enhance (保證@Bean method都為單例的,如果在方法調用中有多次)
- 添加 ImportAwareBeanPostProcessor到beanFactory中的list
第六步 最後從容器中找出所有beanFactoryPostProcessor,防止再postProcessBeanFactory時有
新産生并且未處理過
的處理器
如果有的化依然按照優先級順序加入執行,執行結果隻有一個
registerBeanPostProcessors
與執行beanFactoryPostProcessor方法類似,已然按照優先級順序從目前容器中找出來所有name執行,沒有自定義的化預設隻有這兩個内置的,且都是PriorityOrder的
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>();
把上述處理器找出來并加入到beanFactory中(實際上隻是加到了list中,後續可以直接從目前list中擷取,不用從容器裡拿)----
registerBeanPostProcessors
接着又直接加了一個ApplicationListenerDetector到集合中,未存在singletonObjects中(該類修飾符是預設的,不可在包外通路執行個體化)
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
finishBeanFactoryInitialization
這是真正建立非懶加載單例bean的方法,調用beanFactory.preInstantiateSingletons()
非FactoryBean的情況下,直接去getBean
先允許提前從提早緩存對象中拿,提早暴露的objects或objectFactories,對于自定義的單例第一次拿不到
接着經過一系列判斷後,開始建立
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
getSingleton中會再次嘗試從緩存單例池中拿,将目前bean标記為正在建立中,然後調用對象工廠方法createBean構造bean,将它加入到單例對象池中,并将提早引用池和工廠池中移除目前bean
在工廠方法中,先嘗試是否可以有處理器提早生成一個對象(預設還是null),調用
applyBeanPostProcessorsBeforeInstantiation ->有值 再applyBeanPostProcessorsAfterInitialization
執行目前所有(beanFactory中的處理器集合)後置處理器的postProcessBeforeInstantiation
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
doCreateBean 去執行真正建立bean的過程
createBeanInstance -> 執行個體化bean對應的class
applyMergedBeanDefinitionPostProcessors
->
- 兩個内置後置處理器CommonAnnotationBeanPostProcessor -> 處理PostConstruct,Predestroy, Resource等注解資訊的封裝
-
AutowiredAnnotationBeanPostProcessor->
處理Autowired,Value等注解對應的file,method封裝起來
判斷是否需要提前暴露該對象引用(用于
解決循環依賴
),加到singletonFactories
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
populateBean ->填充bean的屬性
- InstantiationAwareBeanPostProcessor postProcessAfterInstantiationr處理器的調用
- 判斷注入模式resolvedAutowireMode ,AutowireCapableBeanFactory中的幾種
- InstantiationAwareBeanPostProcessor postProcessProperties 用于處理上一步封裝好的InjectedElement的資訊。包括common的ResourceElement, autowired的AutowiredFieldElement,AutowiredMethodElement等,如果沒有要設定進來的對象,會從bean工廠中找,開始進行依賴對象bean的生命周期的建立
initializeBean ->調用初始化方法及生命周期回調
InitDestroyAnnotationBeanPostProcessor 是CommonAnnotationBeanPostProcessor的父接口
- invokeAwareMethods -> BeanNameAware、BeanClassLoaderAware,BeanFactoryAware隻有這三個接口,那麼其他的aware接口是在哪裡調用的呢?ApplicationContextAwareProcessor
-
->applyBeanPostProcessorsBeforeInitialization
,以及ApplicationContextAwareProcessor 執行所有invoke Aware接口方法注意 這裡會調用InitDestroyAnnotationBeanPostProcessor 解析的PostConstruct方法
- invokeInitMethods -> 實作了InitializingBean的方法,調用afterPropertiesSet;同時看bd中是否有自定義不重名的init method也調用
-
-> AbstractAutoProxyCreator 會在這裡進行aop動态代理包裝applyBeanPostProcessorsAfterInitialization
至此,bean的建立就已經結束了!