3.2-1、Spring源碼學習:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

前言

體能狀態先於精神狀態,習慣先於決心,聚焦先於喜好。

承上啓下

本方法用於將配置文件中的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;
		}
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章