1. 程式人生 > >BeanFactory系列介面解析(二)

BeanFactory系列介面解析(二)

目錄

這裡我們通過這些介面的學習,可以大致瞭解BeanFactory體系各介面如何分工合作,以此為基礎供以後邏輯與深入的學習。

1、如圖BeanFactory介面相關結構圖

2、接下來具體分析下各個介面

已經過的這裡只簡單概述下:

(1)、BeanFactory

BeanFactory是Spring bean容器的根介面.

每個bean都是通過string型別bean name或ID進行標識.這邊提供了設計模式單例,原型的替代實現.如果bean name配置為單例,應用內只會獲取到一個例項.如果配置為原型,那麼可以例項化好後填充屬性(基於使用者的配置).BeanFactory作為應用集中配置管理的地方,極大簡便應用開發,這樣開發人員可以集中與業務.

(2)、HierarchicalBeanFactory

提供父容器的訪問功能.至於父容器的設定,需要找ConfigurableBeanFactory的setParentBeanFactory。

(3)、ListableBeanFactory

獲取bean時,Spring 鼓勵使用這個介面定義的api. 還有個Beanfactory方便使用.其他的4個介面都是不鼓勵使用的.

提供容器中bean迭代的功能,不再需要一個個bean地查詢.比如可以一次獲取全部的bean(太暴力了),根據型別獲取bean.在看SpringMVC時,掃描包路徑下的具體實現策略就是使用的這種方式(那邊使用的是BeanFactoryUtils封裝的api).

 如果同時實現了HierarchicalBeanFactory,返回值不會考慮父類BeanFactory,只考慮當前factory定義的類.當然也可以使用BeanFactoryUtils輔助類來查詢祖先工廠中的類. 

 這個介面中的方法只會考慮本factory定義的bean.這些方法會忽略ConfigurableBeanFactory的registerSingleton註冊的單例bean(getBeanNamesOfType和getBeansOfType是例外,一樣會考慮手動註冊的單例).當然BeanFactory的getBean一樣可以透明訪問這些特殊bean.當然在典型情況下,所有的bean都是由external bean定義,所以應用不需要顧慮這些差別.

(4)、AutowireCapableBeanFactory

在BeanFactory基礎上實現對已存在例項的管理.

可以使用這個介面整合其它框架,捆綁並填充並不由Spring管理生命週期並已存在的例項.像整合WebWork的Actions 和Tapestry Page就很實用.一般應用開發者不會使用這個介面,所以像ApplicationContext這樣的外觀實現類不會實現這個介面,如果真手癢癢可以通過ApplicationContext的getAutowireCapableBeanFactory介面獲取. 

(5)、ConfigurableBeanFactory

定義BeanFactory的配置.

這邊定義了太多太多的api,比如類載入器,型別轉化,屬性編輯器,BeanPostProcessor,作用域,bean定義,處理bean依賴關係,合併其他ConfigurableBeanFactory,bean如何銷燬.

定義了兩個作用域: 單例和原型.可以通過registerScope來新增.SCOPE_SINGLETON,SCOPE_PROTOTYPE

(6)、ApplicationContext

用於為應用程式提供配置的中央介面。這在應用程式執行時是隻讀的,但如果實現支援,則可以重新載入。

ApplicationContext介面繼承眾多介面,集眾多介面功能與一身,為Spring的執行提供基本的功能支撐。根據程式設計的“單一職責原則”,其實每個較頂層介面都是“單一職責的”,只提供某一方面的功能,而ApplicationContext介面繼承了眾多介面,相當於擁有了眾多介面的功能,下面看看它的主要功能:

  • 首先,它是個BeanFactory,可以管理、裝配bean,可以有父級BeanFactory實現Bean的層級管理(具體到這裡來說它可以有父級的ApplicationContext,因為ApplicationContext本身就是一個BeanFactory。這在web專案中很有用,可以使每個Servlet具有其獨立的context, 所有Servlet共享一個父級的context),它還是Listable的,可以枚舉出所管理的bean物件。
  • 其次,它是一個ResourceLoader,可以載入資原始檔;
  • 再次,它可以管理一些Message實現國際化等功能;
  • 還有,它可以釋出事件給註冊的Listener,實現監聽機制。

因此,作為Spring提供的較之 BeanFactory 更為先進的IoC容器實現, ApplicationContext 除了擁有BeanFactory 支援的所有功能之外,還進一步擴充套件了基本容器的功能,包括 BeanFactoryPostProcessor 、 BeanPostProcessor 以及其他特殊型別bean的自動識別、容器啟動後bean例項的自動初始化、國際化的資訊支援、容器內事件釋出等

內部方法如下:

@Nullable
String getId();返回此應用程式上下文的唯一ID。

String getApplicationName();返回此上下文所屬的已部署應用程式的名稱。

String getDisplayName();返回此上下文的友好名稱。

long getStartupDate();首次載入此上下文時返回時間戳。

返回父上下文,如果沒有父上下文,則返回{@code null}
這是上下文層次結構的根。
@return父上下文,或{@code null}如果沒有父上下文
@Nullable
ApplicationContext getParent();
通過getAutowireCapableBeanFactory這個方法將AutowireCapableBeanFactory這個介面暴露給外部使用,AutowireCapableBeanFactory這個介面一般在applicationContext的內部是較少使用的,它的功能主要是為了裝配applicationContext管理之外的Bean。
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

(7)、WebApplicationContext

用於為Web應用程式提供配置的介面。 這在應用程式執行時是隻讀的,但如果實現支援,則可以重新載入。

WebApplicationContext是一個介面,並沒有提供比較多的操作,主要有一個函式是getServletContext,用來獲取Servlet上下文,因為spring 的IO容器在web中是儲存在ServletContext中的。

因此專門為web應用準備的,他允許從相對於web根目錄的路勁中裝載配置檔案完成初始化工作,從WebApplicationContext中可以獲得ServletContext的引用,整個Web應用上下文物件將作為屬性放置在ServletContext中,以便web應用可以訪問spring上下文,spring中提供WebApplicationContextUtils的getWebApplicationContext(ServletContext src)方法來獲得WebApplicationContext物件。

內部方法如下:

      /**
       * 用於在成功啟動時將根WebApplicationContext繫結到的Context屬性。
       * 注意:如果根上下文的啟動失敗,則此屬性可以包含異常或錯誤作為值。 使用 
       * WebApplicationContextUtils可以方便地查詢根WebApplicationContext。
       */
	String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

	/**
	 * 請求範圍的範圍識別符號:“request”。除了標準範圍“singleton”和“prototype”之外還支援
	 */
	String SCOPE_REQUEST = "request";

	/**
	 * 會話範圍的範圍識別符號:“會話”。 除了標準範圍“singleton”和“prototype”之外,還支援。
	 */
	String SCOPE_SESSION = "session";

	/**
	 * Scope identifier for the gl全域性Web應用程式範圍的範圍識別符號:“application”。 除了標準範圍“singleton”和“prototype”之外,還支援。
	 */
	String SCOPE_APPLICATION = "application";

	/**
	 * 工廠中ServletContext環境bean的名稱
	 * @see javax.servlet.ServletContext
	 */
	String SERVLET_CONTEXT_BEAN_NAME = "servletContext";

	/**
	 * 工廠中ServletContext init-params環境bean的名稱。
       * <p>注意:可能與ServletConfig引數合併。
       * ServletConfig引數覆蓋同名的ServletContext引數。
	 */
	String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";

	/**
	 * 工廠中ServletContext屬性環境bean的名稱。
	 */
	String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";


	/**
	 * 返回此應用程式的標準Servlet API ServletContext。
	 */
	@Nullable
	ServletContext getServletContext();

(8)、ConfigurableApplicationContext

此介面結合了所有ApplicationContext需要實現的介面。因此大多數的ApplicationContext都要實現此介面。它在ApplicationContext的基礎上增加了一系列配置應用上下文的功能。配置應用上下文和控制應用上下文生命週期的方法在此介面中被封裝起來,以免客戶端程式直接使用。

內部方法:

    /**
     * 應用上下文配置時,這些符號用於分割多個配置路徑
     */
    String CONFIG_LOCATION_DELIMITERS = ",; \t\n";

    /**
     * BeanFactory中,ConversionService類所對應的bean的名字。如果沒有此類的例項的話
     * 則使用預設的轉換規則
     */
    String CONVERSION_SERVICE_BEAN_NAME = "conversionService";

    /**
     * LoadTimeWaver類所對應的Bean在容器中的名字。如果提供了該例項,上下文會使用臨時的ClassLoader
     * 這樣,LoadTimeWaver就可以使用bean確切的型別了
     */
    String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";

    /**
     * Environment類在容器中例項的名字
     */
    String ENVIRONMENT_BEAN_NAME = "environment";

    /**
     * System系統變數在容器中對應的Bean的名字
     */
    String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";

    /**
     * System 環境變數在容器中對應的Bean的名字
     */
    String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";


    /**
     * 設定容器的唯一ID
     */
    void setId(String id);

    /**
     * 設定此容器的父容器
     * 需要注意的是,父容器一經設定就不應該修改。並且一般不會在構造方法中對其進行配置,因為很多時候。
     * 其父容器還不可用。比如WebApplicationContext。
     */
    void setParent(ApplicationContext parent);

    /**
     * 設定容器的Environment變數
     */
    void setEnvironment(ConfigurableEnvironment environment);

    /**
     * 以COnfigurableEnvironment的形式返回此容器的環境變數。以使使用者更好的進行配置
     */
    @Override
    ConfigurableEnvironment getEnvironment();

    /**
     * 此方法一般在讀取應用上下文配置的時候呼叫,用以向此容器中增加BeanFactoryPostProcessor。
     * 增加的Processor會在容器refresh的時候使用。
     */
    void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);

    /**
     * 向容器增加一個ApplicationListener,增加的Listener用於釋出上下文事件如refresh和shutdown等
     * 需要注意的是,如果此上下文還沒有啟動,那麼在此註冊的Listener將會在上下文refresh的時候,全部被呼叫
     * 如果上下文已經是active狀態的了,就會在multicaster中使用
     */
    void addApplicationListener(ApplicationListener<?> listener);

    /**
     * 向容器中注入給定的Protocol resolver,允許多個例項同時存在。
     * 在此註冊的每一個resolver都將會在上下的標準解析規則之前使用。因此,某種程度上來說
     * 這裡註冊的resolver可以覆蓋上下文的resolver
     */
    void addProtocolResolver(ProtocolResolver resolver);

    /**
     * 載入資源配置檔案(XML、properties,Whatever)。
     * 由於此方法是一個初始化方法,因此如果呼叫此方法失敗的情況下,要將其已經建立的Bean銷燬。
     * 換句話說,呼叫此方法以後,要麼所有的Bean都例項化好了,要麼就一個都沒有例項化
     */
    void refresh() throws BeansException, IllegalStateException;

    /**
     * 向JVM註冊一個回撥函式,用以在JVM關閉時,銷燬此應用上下文。
     */
    void registerShutdownHook();

    /**
     * 關閉此應用上下文,釋放其所佔有的所有資源和鎖。並銷燬其所有建立好的singleton Beans
     * 實現的時候,此方法不應該呼叫其父上下文的close方法,因為其父上下文具有自己獨立的生命週期
     * 多次呼叫此方法,除了第一次,後面的呼叫應該被忽略。
     */
    @Override
    void close();

    /**
     * 檢測此FactoryBean是否被啟動過。
     */
    boolean isActive();

    /**
     * 返回此應用上下文的容器。
     * 千萬不要使用此方法來對BeanFactory生成的Bean做後置處理,因為單例Bean在此之前已經生成。
     * 這種情況下應該使用BeanFactoryPostProcessor來在Bean生成之前對其進行處理。
     * 通常情況下,內容容器只有在上下文是啟用的情況下才能使用。因此,在使用此方法前,可以呼叫
     * isActive來判斷容器是如可用
     */
    ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

(9)、ThemeSource

ThemeSource的作用是根據主題名找到具體的主題。 

由可以解析的物件實現的介面。這使得給定“主題”的訊息的引數化和國際化成為可能。

內部方法如下:

@Nullable
Theme getTheme(String themeName);返回給定主題名稱的Theme例項。返回的主題將解析特定於主題的訊息,程式碼,檔案路徑等(例如Web環境中的CSS和影象檔案)

(10)、MessageSource

此介面是一個用於訊息解析的策略介面,其支援訊息的引數化和國際化。 
Spring提供兩種現成的實現類:構建於ResourceBundle基礎之上的ResourceBundleMessageSource和ReloadableResourceBundleMessageSource類用於在不重啟虛擬器的情況下重新載入訊息。

內部方法如下:

/**
	 * 解析code對應的資訊進行返回,如果對應的code不能被解析則返回預設資訊defaultMessage。
	 * @param 需要進行解析的code,對應資原始檔中的一個屬性名
	 * @param 需要用來替換code對應的資訊中包含引數的內容,如:{0},{1,date},{2,time}
	 * @param defaultMessage 當對應code對應的資訊不存在時需要返回的預設值
	 * @param locale 對應的Locale
	 * @return
	 */
	String getMessage(String code, Object[] args, String defaultMessage, Locale locale);

	/**
	 * 解析code對應的資訊進行返回,如果對應的code不能被解析則丟擲異常NoSuchMessageException
	 * @param code 需要進行解析的code,對應資原始檔中的一個屬性名
	 * @param args 需要用來替換code對應的資訊中包含引數的內容,如:{0},{1,date},{2,time}
	 * @param locale 對應的Locale
	 * @return 
	 * @throws NoSuchMessageException 如果對應的code不能被解析則丟擲該異常
	 */
	String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;

	/**
	 * 通過傳遞的MessageSourceResolvable對應來解析對應的資訊
	 * @param resolvable 
	 * @param locale 對應的Locale
	 * @return 
	 * @throws NoSuchMessageException 如不能解析則丟擲該異常
	 */
	String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

(11)、ResourceLoader

 Spring為了方便程式呼叫不同型別的資源而定義的介面。Spring提供若干實現,方便我們針對不同的資源獲取資原始檔以及對具體內容的操作。常用的有以下三種:

  1. 通過 FileSystemResource 以檔案系統絕對路徑的方式進行訪問;
  2. 通過 ClassPathResource 以類路徑的方式進行訪問;
  3. 通過 ServletContextResource 以相對於Web應用根目錄的方式進行訪問。

用於載入資源的策略介面(策略包括classpath或者file system等型別)。Spring中的的所有應用上下文都應該擁有此功能和其拓展功能-ResourcePatternResolver。 
DefaultResourceLoader是此介面的一個實現,通常在ApplicationContext以外的類中使用,如ResourceEditor

內部方法如下:

    /** 如果要載入根目錄下的資源,則使用classpath開頭 */
    String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;


    /**
     * 返回一個能解析指定目錄Resource的物件
     * 該物件必須是可重用的,例如必須支援Resource的getInputStream方法多次呼叫而保持不變
     * 必須支援全限定的URLs,例如"file:C:/test.dat"
     * 必須支援全限定的偽URLs,例如"classpath:test.dat"
     * 必須支援相對檔案路徑,如"WEB-INF/test.dat"
     * 需要注意的是,引數中指定了路徑的Resource不一定存在,在使用資源之前
     * 必須先呼叫Resource的exists方法檢查資源是否存在
     */
    Resource getResource(String location);

    /**
     * 返回此類使用的ClassLoader
     * 如果有需要使用ClassLoader的程式碼,可以直接呼叫此方法來得到例項,而不需要
     * 通過Thread上下文獲取ClassLoader
     */
    ClassLoader getClassLoader();

(12)、ApplicationEventPublisher

ApplicationEventPublisher是ApplicationContext的父介面之一。這介面的作用是:該介面的功能是publish Event,向事件監聽器(Listener)傳送事件訊息

功能就是釋出事件,也就是把某個事件告訴的所有與這個事件相關的監聽器

內部方法如下:

/**
	 *通知在應用程式事件的此應用程式中註冊的所有<strong>匹配</ strong>偵聽器。 事件可以是框架事件(例如RequestHandledEvent)或特定於應用程式的事件。
	 */
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}

	/**
	 * 通知在此事件應用程式中註冊的所有<strong>匹配</ strong>偵聽器。<p>如果指定的{@code事件}不是{@link ApplicationEvent},則它將包裝在{@link PayloadApplicationEvent}中。
	 */
	void publishEvent(Object event);

相關推薦

BeanFactory系列介面解析

目錄 這裡我們通過這些介面的學習,可以大致瞭解BeanFactory體系各介面如何分工合作,以此為基礎供以後邏輯與深入的學習。 1、如圖BeanFactory介面相關結構圖 2、接下來具體分析下各個介面

談談-Android-PickerView系列之源碼解析

需求 動態 () comm tag 多個 來源 ntc 寬高 前言   WheelView想必大家或多或少都有一定了解, 它是一款3D滾輪控件,效果類似IOS 上面的UIpickerview 。按照國際慣例,先放一張效果圖:   以上是Android-PickerView

【Servicemesh系列】【Envoy原始碼解析】一個Http請求到響應的全鏈路

目錄 1. http連線建立 當有新連線過來的時候,會呼叫上一章節所提及的被註冊到libevent裡面的回撥函式。我們回顧一下,上一章節提及了,會有多個worker註冊所有的listener,當有一個連線過來的時候,系統核心會排程一個執行緒出來交付

死磕 java同步系列之ReentrantLock原始碼解析——條件鎖

問題 (1)條件鎖是什麼? (2)條件鎖適用於什麼場景? (3)條件鎖的await()是在其它執行緒signal()的時候喚醒的嗎? 簡介 條件鎖,是指在獲取鎖之後發現當前業務場景自己無法處理,而需要等待某個條件的出現才可以繼續處理時使用的一種鎖。 比如,在阻塞佇列中,當佇列中沒有元素的時候是無法彈出一個元素

[轉]畢設- 深入HBase架構解析

node 角度 發送 under 收集 .org fig 服務器 url 深入HBase架構解析(二) 前言 這是《深入HBase架構解析(一)》的續,不多廢話,繼續。。。。 HBase讀的實現 通過前文的描述,我們知道在HBase寫時,相同Cell(RowKe

Spring源碼:IOC原理解析

main 節點 定義 nat ner multicast esp loading more 版權聲明:本文為博主原創文章,轉載請註明出處,歡迎交流學習! 接著上一章節的內容,我們來分析當new一個FileSystemXmlApplicationContext對

Dubbo服務框架解析

換行符 spi track .net int apt thread exce -i 本節介紹dubbo-common,dubbo-common是公共邏輯模塊,包含Util類、通用模型,是其他模塊的基礎。 擴展機制 SPI SPI是擴展點的註解。

CDN HTTPS 最佳實踐系列——HTTP/2

https 證書 cdn 背景HTTP/2 是最新的 HTTP 協議,已於2015年5月份正式發布,Chrome、 IE11、Safari 以及 Firefox 等主流瀏覽器已經支持 HTTP/2 協議。阿裏雲 CDN 在2016年7月份開始全網支持 HTTP/2,是國內第一家全網支持 HTTP/

volatile關鍵字解析

禁止 new incr lock 解析 static style ron running volatile詳解接下來,我們詳細講述一下volatile關鍵字volatile關鍵字具有兩重語義 保證了不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這個新

SDWebImage源代碼解析

gate using win article try 情況 zed ntc 最大 上一篇:SDWebImage源代碼解析(一)

Spring 源碼解析加載配置文件2

文件 pla eager useful customize string protected rop orm 接上一章,我們來具體分析下configureAndRefreshWebApplicationContext(ConfigurableWebApplicationCo

if選擇結構解析

否則 switch scan 輸入 嵌套 int 簡單 移動 沒有 1.switch選擇結構: 語法: switch (key) { case value: break; case valu

Exchange 2016異地容災系列-路由器部署

不同 配置步驟 server 域控制器 環境 alt 安裝 啟用路由和遠程訪問 功能 搭建部署Exchange 2016異地容災環境,我們需要有兩個AD站點,在本次實驗當中,不可避免的需要有兩個不同網段的IP,所以需要部署一個路由器,可以使用windows server 2

Inno Setup 3 :語法解析

nes 多個 appid war 層次 需要 ace lena disk   接上回。安裝腳本段用於解析腳本中各個段的含義及使用方法。其包括[Setup]段、[Files]段、[Run]段等共17個字段,下面逐一進行分析。 [Setup]  &

Person Re-identification 系列論文筆記:A Discriminatively Learned CNN Embedding for Person Re-identification

triplet put ali com multi 深度學習 native alt 出現   A Discriminatively Learned CNN Embedding for Person Re-identification Zheng Z, Zheng L, Ya

Formik官方應用案例解析同步校驗

ssa tools require min roc 是否 支持 array tps 簡介 官方示例工程formik-09x-synchronous-validation-example展示的是基於Formik的表單開發中如何進行定制的同步校驗的問題。 上一個實例相關內容回顧

mybatis通用mapper源碼解析

bool emp nts content new type() als append column 1.javabean的屬性值生成sql /** * 獲取所有查詢列,如id,name,code... * * @param entityC

dva源碼解析

不一定 strong dispatch tab lec 什麽 們的 select 不可變 轉載 :原文https://blog.csdn.net/zhangrui_web/article/details/79607034 dva的8個基礎概念: 數據流向 數據的

rest-assured介面自動化:往execl中增加用例,自動執行所有介面

利用空閒之餘,寫了第一個介面自動化測試demo, 通過讀取execl中的介面測試用例,介面自動執行。(這裡跟很多網上的介面自動化有點不同的是:無需再寫程式碼,只需要從execl中增加用例,就可執行)。 這是execl的模板: 這個模板可以很好的管理專案的各個模組,看起來也是簡潔,也是頗為喜

Spring原始碼解析——元件註冊2

    import com.ken.service.BookService; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.