一、refresh 方法
SpringBoot 加載 bean 操作主要在 AbstractApplicationContext 類 refresh 方法里,它的流程圖如下:
代碼如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 容器狀態設置,初始化屬性設置,檢查必備屬性是否存在
prepareRefresh();
// 設置beanFactory序列化id,獲取beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設置 beanFactory 屬性,添加后置處理器,設置忽略的自動裝配接口,注冊部分組件
prepareBeanFactory(beanFactory);
try {
// 子類重寫以在 BeanFactory 完成創建后做進一步設置
postProcessBeanFactory(beanFactory);
// 調用BeanDefinitionRegistryPostProcessor實現向容器內添加bean的定義
// 調用BeanFactoryPostProcessor實現向容器內添加bean的定義添加屬性
invokeBeanFactoryPostProcessors(beanFactory);
// 找到BeanPostPocessor的實現,排序后注冊進容器內
registerBeanPostProcessors(beanFactory);
// 初始化國際化相關屬性
initMessageSource();
// 初始化事件廣播器。注冊到容器當中
initApplicationEventMulticaster();
// 創建web容器。如果是web環境當中,構建一個web容器,如tomcat,jetty等。
onRefresh();
// 添加容器內事件監聽器至事件廣播器中
// 派發早期事件
registerListeners();
// 初始化剩下的單實例 Bean
registerListeners(beanFactory);
// 初始化生命周期處理器
// 調用生命周期處理器的onRefresh方法
// 發布ContextRefreshedEvent 事件
// JMX相關處理
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 銷毀已創建的單例
destroyBeans();
// 重置標記
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// 清除緩存
resetCommonCaches();
}
}
}
二、Bean實例化流程
bean 實例化流程流程是在 onRefresh方法的 finishBeanFactoryInitialization中,進入該方法:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}