文章目錄
前言
體能狀態先於精神狀態,習慣先於決心,聚焦先於喜好。
承上啓下
本方法用於將配置文件中的bean加載到 beanDefination 中,然後將beanDefination 放入到 beanFactory,但是需要注意到是,只是加載了 bean到定義信息,還沒有進行注入、實例化等工作.
AbstractApplicationContext.obtainFreshBeanFactory(
org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(
通知子類 refresh 內部的 bean factory
/**
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//創建一個 beanFactory 對象
refreshBeanFactory();
//bean配置文件加載和解析工作已經完成,這裏只是簡單的驗證一下非空,如果非空則返回已加載完畢的值
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
AbstractRefreshableApplicationContext.refreshBeanFactory(
org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(
用於創建一個BeanFactory(DefaultListableBeanFactory ),爲之後使用,如果之前的操作存在這麼個 BeanFactory,則先將之前的 BeanFactory 進行銷燬。
新創建的 BeanFactory 將服務於 下一階段 上下文的聲明週期
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果 beanFactory已存在,則銷燬,這裏的操作都是用了 對象鎖進行同步
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//創建 BeanFactory,內部會檢測父工廠,默認父工廠爲null
DefaultListableBeanFactory beanFactory = createBeanFactory();
//設置序列化id,以 webApplicationContext 的id相同
beanFactory.setSerializationId(getId());
//更新 allowBeanDefinitionOverriding 和 allowCircularReferences 的值,默認這段代碼沒用,不會修改默認值,除非你beanFactory.set*Name 修改了值
customizeBeanFactory(beanFactory);
//爲 beanFactory 記載 bean定義文件
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
createBeanFactory()
看這個方法建議先看下 認識 DefaultListableBeanFactory,這裏面有對 DefaultListableBeanFactory 和其父類的基本常量的介紹。
比如默認cglib動態代理、允許覆蓋同名bean、允許循環依賴、允許立即加載需要的類、不允許使用原始類型注入作爲解決循環依賴的方法等等。
再一個需要忽略依賴和注入的接口,默認只有 BeanFactory interface,但是在 DefaultListableBeanFactory 中其實增加了 BeanNameAware、BeanFactoryAware和BeanClassLoaderAware 三個接口要被忽略
protected DefaultListableBeanFactory createBeanFactory() {
//getInternalParentBeanFactory() 返參默認爲null,即沒有父工廠
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
loadBeanDefinitions(beanFactory);
org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(
這個步驟比較關鍵,用於加載定義 bean 的配置文件,一般我們會定義一個或者多個 applicationContext.xml,當然,這個功能最終是體現在 loadBeanDefinitions(beanDefinitionReader); 中的
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//爲 beanFactory 創建一個 XmlBeanDefinitionReader 對象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 使用上下文資源加載 變量參數,配置 bean 定義的reader
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 允許一個子列提供自定義的 reader對象的實現,然後再開始具體bean 定義加載過程
//默認這是一個空方法
initBeanDefinitionReader(beanDefinitionReader);
//正式加載
loadBeanDefinitions(beanDefinitionReader);
}
XmlWebApplicationContext.loadBeanDefinitions(
org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(
使用 XmlBeanDefinitionReader 加載 bean定義文件。
bean factory的聲明週期由 refreshBeanFactory 方法控制,本方法僅用於加載或者註冊 bean定義文件。
內部委託 ResourcePatternResolver 將本地文件進行解析爲資源實例。對於這部分邏輯的解析再寫一篇文章 reader.loadBeanDefinitions(configLocation);
* <p>Delegates to a ResourcePatternResolver for resolving location patterns
* into Resource instances.
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
//考慮通配符的情況,對文件路徑進行轉化
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
//內部委託 ResourcePatternResolver 將本地文件進行解析爲資源實例
reader.loadBeanDefinitions(configLocation);
}
}
}
AbstractRefreshableApplicationContext.getBeanFactory()
org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory()
這個方法沒有特別複雜的邏輯,只是判斷一下 beanFactory 是否存在
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}