Spring iOC主流程初始化方法org.springframework.context.support.AbstractApplicationContext#refresh方法
##### 啓動測試類
@Test
public void beanTest(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Result bean = context.getBean(Result.class);
context.close();
}
}
1.ClassPathXmlApplicationContext 構造方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
調用了另一個構造方法
2. ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
/**
* 初始化父類
*/
super(parent);
/**
* 設置本地資源配置
*/
setConfigLocations(configLocations);
/**
* 完成Spring Bean的初始化
*/
if (refresh) {
/**
* 構造方法
*/
refresh();
}
}
父上下文是空
設置配置文件setLocation
public void setConfigLocations(@Nullable String... locations) {
/**
* 配置文件可以有多個循環處理
*/
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
/**
* 把傳進來的配置文件賦值給一個數組
*/
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
refresh()核心方法
public void refresh() throws BeansException, IllegalStateException {
/**
* 加鎖,說明併發執行,很多地方都有調用
* registerShutdownHook 也調用了
* close()方法也調有了,
* 容器在啓動時,不能調Close的方法
*/
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/**
* 預初始化
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/**
*
* 創建BeanFactory工廠,告訴子類去刷新內部BeanFactory,
* 加載Bean信息,並封裝爲BeanDefinition,並註冊到BeanDefinitionRegistry
* key-value key :bean的id value就是BeanDefinition
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/**
* 準備BeanFactory,進行一些設置
* Context的類加載器
*/
prepareBeanFactory(beanFactory);
try {
/**
* BeanFactory準備完成後,後置處理器增強,空方法
*/
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
/**
* 實例化實現了BeanFactoryPostProcessor接口的類中構造方法
* 並調用用postProcessBeanFactory 方法
*
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
/**
*將實現了BeanPostProcessor的構造方法
*/
registerBeanPostProcessors(beanFactory);
/**
* 初始化國際華資源MessageSource組牛
*/
// Initialize message source for this context.
initMessageSource();
/**
* 初始化事件派發器
*/
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
/**
* 空方法
* 如果子類重寫了這個方法就,調用子類重寫的方法tomcat jetty之類的
*/
// Initialize other special beans in specific context subclasses.
onRefresh();
/**
* 註冊應用監聽器就是實現了ApplicationContextListener接口Bean
*/
// Check for listener beans and register them.
registerListeners();
/**
* 執行構造方法1
* setter方法2
* 實現了BeanNameAware接口的setBeanName方法3
* 實現了BeanFactoryAware接口的 setBeanFactory(BeanFactory beanFactory)方法4
* 實現了ApplicationContextAware接口的setsetApplicationContext 方法5
* 實現了BeanPostProcessor接口的postProcessBeforeInitialization方法6 ,AOP原理
* 標有PostConstruct註解的方法 7
* 實現了InitializingBean接口的afterPropertiesSet方法8
* 調用配置了init-method方法 9
* 實現了BeanPostProcessor接口的postProcessAfterInitialization方法 10
*
*/
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
/**
* 完成刷新Context,主要調用org.springframework.context.LifecycleProcessor接口onRefresh方法,發佈事件ContextRefreshedEvent事件
*/
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
/**
* 銷燬Bean
*/
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
/**
* 重置Active標誌爲false
* this.active.set(false);
*/
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
/**
* 清空緩存
*/
resetCommonCaches();
}
}
}