1. 程式人生 > >深入研究Spring-IoC:兩種設計和實現

深入研究Spring-IoC:兩種設計和實現

一.Sprng IOC

  • 解除了物件例項化造成的耦合現象;將物件的建立和對生命週期的管理交給了容器來管理,可以通過注入的方式將IOC容器中的物件供給開發者使用,極大方便了開發。

二.IOC容器系列的兩種設計和實現–BeanFactory和ApplicationContext

  • Spring
    IOC容器的設計中,IOC容器是一個統一稱呼,具體擔當容器的角色的Bean可以主要分為兩種:BeanFactory系列、ApplicationContext系列;

  • 前一種是簡單實現了BenFacotry這個介面的實現思路。後一種不僅僅實現
    BeanFacorty介面,還實現了其他介面,這樣就賦予了ApplicationContext系列容器更多的特性。

  • PS:在實際的開發中以第二中形式為多。

這裡寫圖片描述

  • PS:紅色的是BeanFacotry系列容器;綠色的是ApplicationContext系列。 兩條設計思路:

  • BeanFatory:

    1. 在這條設計路徑中,BeanFactory介面定義了基本的IOC容器特性GetBean())。

    2. HierarchicalBeanFactory介面增加了getParentBeanFacory()的介面功能,使得BeanFacotry具備了雙親IOC容器的管理功能。

    3. ConfigurableBeanFatory介面定義了對BeanFactory的配置功能,比如setParentBeanFactory()、addBeanPostProcessor()配置bean的後只處理器等。

  • ApplicationContext:

  • 第二條介面設計主線是,以ApplicationContext應用上下文介面為核心的介面設計,這裡涉及的主要介面設計有,從BeanFactory到ListableBeanFactory,再到ApplicationContext,再到我們常用的WebApplicationContext或者ConfigurableApplicationContext介面。

  • 我們常用的應用上下文基本上都是ConfigurableApplicationContext或者WebApplicationContext的實現。

  • 在這個介面體系中,ListableBeanFactory和HierarchicalBeanFactory兩個介面,連線BeanFactory介面定義和ApplicationContext應用上下文的介面定義。在ListableBeanFactory介面中,細化了許多BeanFactory的介面功能,比如定義了getBeanDefinitionNames()介面方法;對於ApplicationContext介面,通過繼承MessageSource、ResourceLoader、ApplicationEventPublisher介面,在BeanFactory簡單IoC容器的基礎上添加了許多對高階容器的特性的支援。

    區別:

    1. BeanFactory負責讀取bean配置文件,管理bean的載入,例項化,維護bean之間的依賴關係,負責bean的宣告週期。
      ApplicationContext除了提供上述BeanFactory所能提供的功能之外,還提供了更完整的框架功能:
      a、提供文字資訊解析,支援I18N
      b、提供載入檔案資源的通用方法
      c、向註冊為監聽器的Bean傳送事件
      d、ApplicationContext介面擴充套件BeanFactory介面
      e、ApplicationContext提供附加功能

    2. 硬編碼區別:

XmlBeanFactory bFactory = new XmlBeanFactory(new ClassPathResource("Spring.xml"));
BeansDemoClass beans = (BeansDemoClass) bFactory.getBean("beansDemoClass");
ApplicationContext aContext = new ClassPathXmlApplicationContext("Spring.xml");
BeansDemoClass beans = (BeansDemoClass)aContext.getBean("beansDemoClass");
  1. 初始化
    BeanFactory當需要呼叫時讀取配置資訊,生成某個類的例項。如果讀入的Bean配置正確,則其他的配置中有錯誤也不會影響程式的執行。而ApplicationContext在初始化時就把 xml 的配置資訊讀入記憶體,對 XML 檔案進行檢驗,如果配置檔案沒有錯誤,就建立所有的Bean,直接為應用程式服務。相對於基本的BeanFactory,ApplicationContext 唯一的不足是佔用記憶體空間。當應用程式配置Bean較多時,程式啟動較慢。

  2. 補充
    ApplicationContext會利用Java反射機制自動識別出配置檔案中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,並自動將它們註冊到應用上下文中;而BeanFactory需要在程式碼中通過手工呼叫addBeanPostProcessor()方法進行註冊。
    Ps:主要作用是就是讓容器知道程式中都有哪些Bean。

三.建立IOC用到的核心類:Resource、BeanDefinition、BeanFactory

  • Resource :主要作用是指定IOC容器載入物件的資料來源。

    1. 在Spring內部,針對於資原始檔有一個統一的介面Resource表示。其主要實現類有ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。

    2. ClassPathResource可用來獲取類路徑下的資原始檔。假設我們有一個資原始檔test.txt在類路徑下,我們就可以通過給定對應資原始檔在類路徑下的路徑path來獲取它,new
      ClassPathResource(“test.txt”)。

    3. FileSystemResource可用來獲取檔案系統裡面的資源。我們可以通過對應資原始檔的檔案路徑來構建一個FileSystemResource。FileSystemResource還可以往對應的資原始檔裡面寫內容,當然前提是當前資原始檔是可寫的,這可以通過其isWritable()方法來判斷。FileSystemResource對外開放了對應資原始檔的輸出流,可以通過getOutputStream()方法獲取到。

    4. UrlResource可用來代表URL對應的資源,它對URL做了一個簡單的封裝。通過給定一個URL地址,我們就能構建一個UrlResource。

    5. ByteArrayResource是針對於位元組陣列封裝的資源,它的構建需要一個位元組陣列。

    6. ServletContextResource是針對於ServletContext封裝的資源,用於訪問ServletContext環境下的資源。ServletContextResource持有一個ServletContext的引用,其底層是通過ServletContext的getResource()方法和getResourceAsStream()方法來獲取資源的。

這裡寫圖片描述

  • BeanDefinition:載入物件的資料結構(個人愚見就是我們自己寫的類的抽象結構再加上什麼其他資訊);

    1. Spring通過定義BeanDefinition來管理Spring應用中各種物件以及他們之間的依賴關係。BeanDefinition抽象了我們對Bean的定義,是讓容器起作用的主要資料型別。
  • BeanFactory:用於盛放物件的Bean;

    1. BeanFactory是用於生產的Bean的工廠,如果有興趣可以和FactoryBean比較一下。其中,定義了容器的基本規範(比如說能盛水的木質東西就是桶)用來產生各種各樣的IOC容器。
  • 總結:如果把IOC比喻成水桶,那麼BeanFactory是木桶,BeanDefinition是桶裡的水,Resource是水來的方法。其中水桶按照樣式大小分為不同的系列(BeanFacotry和ApplicationContext),而水(Bean)也有髒水和乾淨水之分(BeanDefinition是不同Bean的抽象)。

四.IOC容器初始化的三個步驟

1.Resource定位

  • Resource是封裝的I/O操作類的介面,用於讀取指定(URL、XML)的資源內容。通常由Resource介面的實現類來完成。例如:ClassPathResource
    或者ClassPathContextResource 來實現。
  • -

2.BeanDefinition載入

  1. 將我們定義好的Bean(類;一般為XML中的Bean)通過Resource讀取,然後解析成Documnet物件,然後再解析成Bean的抽象的資料結構(BeanFactory可以根據這些資料結構例項化出一個我們定義的Bean類)

3.向ioc註冊這些BeanDefinition

  • 拿到BeanDefinition後通過註冊(告訴BeanFactory有哪些Bean)儲存到BeanFatory中,以HashMap(Key,BeanDefinition)的形式儲存起來,可以通過BeanFatory的例項呼叫getBean(Key)的方法,Spring會通過反射的機制給我注入我們想要的Bean;

學習部落格:
http://blog.csdn.net/u011202334/article/details/51509235
《Spring技術內幕》