spring-ioc容器

IOC(inverse of control,控制-反轉)

一、ioc概述

1.ioc的類型

        ioc主要可以劃分成三種類型:構造函數注入屬性注入接口注入


 
2.通過容器完成依賴關係注入:

        通過xml的方式配置Bean,在容器啓動時,spring根據xml配置文件的
        描述信息自動實例化Bean並完成依賴關係的裝配,
        這種實例化並注入依賴的能力是通過java的反射來實現的


        
二、相關java基礎知識

    java語言允許通過程序化的方式間接對Class進行操作。
    Class文件有類裝載器裝載後, 在JVM中將形成一份描述Class結構的元信息對象,
    通過該元信息對象可以獲知Class的結構信息,如構造函數、屬性和方法等。
    Java允許用戶藉由這個與Class相關的元信息對象間接調用Class對象的功能,
    這就爲使用程序化方式操作Class對象開闢了途徑


    
 1、類裝載器就ClassLoader


 
    類裝載器就是尋找類的字節碼文件並構造出類在JVM內部表示對象的組件
    類裝載器把一個類裝入JVM中,需要經過一下步驟:
    (1)裝載:查找和導入Class文件
    (2)鏈接:執行校驗、準備和解析步驟,其中解析步驟是可以選擇的。
        ①校驗:檢查載入Class文件數據的正確性
        ②準備:給類的靜態變量分配存儲空間
        ③解析:將符號引用轉換爲直接引用
    (3)初始化:對類的靜態變量、靜態代碼塊執行初始化工作
    


JVM裝載類的時使用“全盤負責委託機制”

    “全盤負責”:是指當一個ClassLoader裝載一個類時,除非顯式地使用另一個“ClassLoader”,
    該類所依賴及引用的類也有這個ClassLoader載入;
    
    “委託機制”:是指先委託父裝載器尋找目標類,只有在找不到的情況下才從自己的類路徑中查找
    並裝載目標類;
    
    正因爲有了“全盤負責委託機制”,java.lang.String 永遠是由根裝載器來裝載的,
    避免有人編寫一個惡意的基礎類(例如String)裝載到JVM中


    
 2.java反射機制
 


    Class反射對象描述類的語義結構,
    從Class對象可以獲取構造函數、成員變量、方法類等類元素的反射對象
    主要的反射類有三個:Controller、Method、Field  其他還有package、AnnotatedElement反射類
    在訪問private或protected成員變量或方法時,必須通過setAccessible(boolean access)方法取消
    java語言檢查,否則將拋出IllegalAccessException


三、資源訪問利器 Resource

 

1、資源抽象接口

 

    spring Resource接口爲應用提供了更強的底層資源訪問能力。該接口擁有對應不同資源類型的實現類
    主要方法:
        > boolean exists(): 資源是否存在
        > boolean isOpen(): 資源是否打開
        > URL getUTL() throws IOException: 如果底層資源可以表示成URL,則該方法返回對應不同類型的實現類
        > File getFile() throws IOException: 如果底層資源對應一個文件,則該方法返回對應的File對象
        > InputStream getInputStream() throws IOException: 返回資源對應的輸入流
    > WritableResource: 可寫資源接口 實現類有FileSystemResource和PathResource
    > ByteArrayResource: 二進制數組表示的資源
    > ClassPathResource: 類路徑下的資源
    > FileSystemResource: 文件系統資源
    > InputStreamResource: 以輸入流返回表示的資源
    > ServletContextResource: 爲訪問Web容器上下文中的資源而設計的類
    > UrlResource: 使用戶能夠訪問任何可以通過URL表示的資源
    > PathResource: spring4.0提供讀取資源文件的一個通用類
    


2、資源加載


    spring能通過不同的資源地址前綴識別不同的資源類型。支持Ant風格通配符資源地址:? * **
    資源地址前綴有:classpath:、file:、http://、ftp://等。
    或者是沒有前綴,根據ApplicationContext的具體實現類採用對應類型的Resource
    
    在發佈時如果資源配置文件被打包到jar包中。recource.getFile就無法讀取了,
    從而造成部署實施時出現意想不到的問題。因此我們建議儘量以流的方式讀取
    避免環境不同造成問題


    
四、BeanFactory和ApplicationContext


    spirng通過配置文件描述Bean與Bean之間的依賴關係,利用Java語言的反射功能實例化Bean並建立Bean之間的依賴關係。
    springIOC的容器在完成這些底層工作的基礎上還提供了Bean實例緩存、生命週期管理、Bean實例代理、事件發佈、資源裝載等高級服務。
    BeanFactory是spring框架最核心的接口,它提供了高級IOC的配置機制
    BeanFactory是IOC容器,ApplicationContext爲應用上下文,也稱爲Spring容器
    BeanFactort是Spring框架的基礎設施面向Spring本身;ApplicationContext面向使用Spring框架的開發者


    1.BeanFactory在初始化容器時沒有實例化Bean,直到第一次訪問某個Bean時才實例化目標Bean
      而ApplicationContext則在初始化應用上下文時就實例化所有單實例的Bean。
        因此ApplicationContext的初始化時間會比BeanFactory稍長一些,不過稍後的調用則沒有“第一次懲罰”的問題
    
    2.通過HierarchicalBeanFactory接口,spring的IOC容器可以建立父子層級關聯的容器體系
        子容器可以訪問父容器中的Bean,但父容器不能訪問子容器中的Bean。
        在容器內,Bean的Id必須是唯一的,但子容器可以擁有一個和父容器id相同的Bean。

五、Bean的生命週期


    Bean生命週期多個特定的生命階段組成,每個生命階段都開出了一扇門,允許外界藉由此門對Bean施加控制
    spring中可以從兩層面定義Bean的生命週期: 
        第一個層面是Bean的作用範圍
        第二個層面是實例化Bean時所經歷的一系列階段       


1.BeanFactory中Bean的生命週期


    1.當調用者通過getBean(beanName)向容器請求某一個Bean時,如果容器註冊了
        org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口
      ,實例化Bean之前,將調用接口的postProcessBeforeInstantiation方法。
    2.根據配置情況調用Bean構造函數或工廠方法實例化Bean
    3.如果容器註冊了InstantiationAwarePostProcessor接口,那麼在實例化Bean之後,
      用該接口的postProcessAfterInstantiation()方法,可在這裏對已經實例化的對象進行梳理打扮
    4.如果Bean配置了屬性信息,那麼容器在這一步着手將配置值設置到Bean對應的屬性中,不過在設置每個屬性之前
      將先調用InstantiationAwareBeanPostProcessor接口的postProcessValues()方法。
    5.調用Bean的屬性設置方法設置屬性值
    6.如果Bean實現了 org.springframework.beans.factory.BeanNameAWare 接口,則將調用setBeanName()接口方法,
      將配置文件中該Bean對應的名稱設置到Bean中
    7.如果Bean實現了org.springframework.beans.factory.BeanFactoryAware接口,則將調用setBeanFactory()接口方法,
      將BeanFactory容器實例設置到Bean中。
    8.如果BeanFactory裝配了org.springframework.beans.factory.config.BeanPostProcessor後處理器,
      則將嗲用BeanPostProcessor的Object postProcessBeforeInitialzation(Object bean,String beanName)接口方法
      對Bean進行加工操作。
        其中入參bean是當前正在處理的Bean,而beanName是當前Bean的配置名,返回的對象爲加工處理後的Bean
        用戶可以使用該方法對某些Bean進行特殊處理,甚至改變Bean的行爲。
        BeanPostProcessor在Spring框架中佔有重要的地位,爲容器提供對Bean後續加工處理的切入點
        Spring提供的AOP、動態dialing等功能都通過BeanPostProcessor實施
    9.如果Bean實現了InitialzaingBean接口,則將調用接口的afterPropertiseSet()方法
    10.如果<bean>中通過init-method屬性定義了初始化方法,則將執行這個方法。
    11.BeanPostProcessor後處理器定義了兩個方法:
        其一是postProcessBeforeInitialization(),在第8步調用;
        其二是Object postProcessAfterInitialization(Object bean,String beanName),這個方法在此時調用,
              容器再次獲得對Bean進行加工處理的機會
    12.如果在<bean>中指定Bean的作用範圍爲scope = "prototype",則將Bean返回給調用者,調用者負責Bean後續的生命管理,
       spring不再管理這個Bean的生命週期。如果將作用範圍設置爲scope="singleton",則將Bean放入SpringIoc容器的緩存池中,
       並將Bean引用返回給調用者,Spring繼續對這些Bean進行後續的生命管理。
    13.對於scope="singleton"的Bean(默認情況),當容器關閉時,將觸發Spring對Bean後續生命週期的管理工作。
       如果Bean實現了DisposableBean接口,將調用接口destroy方法,可以在此編寫釋放資源,記錄日誌等操作。
    14.對於scope="singleton"的Bean,如果通過<bean>的destroy-method屬性指定了Bean的銷燬方法,那麼Spring將執行Bean等的這個方法,
      完成Bean資源的釋放等操作。


BeanFactory生命週期總結


    Bean完整的生命週期中方法大致可以分爲四類:
        1.Bean自身的方法:
            如調用Bean構造函數實例化Bean、調用Setter設置Bean的屬性值及通過<bean>的init-method和destroy-method所指定的方法
        2.Bean級生命週期接口方法:
            如BeanNameAware、BeanFactoryAware、InitializatingBean和DisposableBean,這些接口方法有Bean類直接實現
        3.容器級生命週期接口方法:
            由InstantiationAwareBeanPostProcessor和BeanPostProcessor這兩個接口實現的,一般稱他們的實現類爲“後處理器”。
            後處理器接口一般不由Bean本身實現,他們獨立於Bean,實現類以容器附加裝置的形式註冊到Spring容器中,並通過接口
            反射爲Spring容器掃描識別。當Spring容器創建任何Bean的時候,這些後處理器都會發生作用,所以這些處理器的影響是全局性的。
            當然,用戶可以通過合理地編寫後處理器,讓其僅對感興趣的Bean進行加工處理
        4.工廠後處理器接口方法:
             包括AspectJWeavingEnable、CustomerAutowireConfigurer、ConfigurationClassPostProcessor等方法。
             工廠後處理器也是容器級的,在應用上下文裝配配置文件後立即調用


             
2.ApplicationContext中Bean的生命週期


    1、Bean在應用上下文中的生命週期與在BeanFactory中類似,不同的是在第一步前如果配置了工廠後處理器接口BeanFactoryPostProcessor
       的實現類,則在應用上下文加載配置後,初始化Bean實例之前將調用這些BeanFactoryPostProcessor對配置信息進行加工處理。
       工廠後處理器是容器級的,僅在應用上下文初始化時調用一次,其目的是完成一些配置文件的加工處理工作
    2.如果Bean實現了org.springframework.context.ApplicationContextAware接口,則會在第八步setBeanFactory後
      調用setApplicationContext方法
    3.ApplicationContext與BeanFactory的另一個最大不同是:
        ApplicationContext會利用java反射機制自動識別出配置文件中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessor
        和BeanFactoryPostProcessor,並自動將它們註冊到上下文中
        BeanFactory則在代碼中通過手工調用addBeanPostProcessor()方法進行註冊
  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章