spring-IoC容器

1. 注入方式

  1. 構(gòu)造方法注入
    • 對(duì)象構(gòu)造完恋捆,馬上可以使用
    • 參數(shù)過(guò)長(zhǎng)維護(hù)復(fù)雜棵逊,無(wú)法繼承万矾,無(wú)默認(rèn)值
  2. setter方法注入
    • 方法可以命名悼吱,可以繼承,可以有默認(rèn)值
    • 無(wú)法構(gòu)造完成后良狈,立馬使用
    • 可以解決 scope = singleton 的bean 的循環(huán)依賴
      • 提前暴露一個(gè)單例工廠方法后添,從而使其他bean能引用到該bean
        • addSingletionFactory
  3. 接口注入
    • 基本不用,強(qiáng)制實(shí)現(xiàn)不必要的接口

2. 兩種類型的容器

BeanFactory 和 ApplicationContext 繼承關(guān)系
  • BeanFactory 薪丁∮鑫鳎基礎(chǔ)類型IoC容器,提供完整的IoC服務(wù)支持窥突。如果沒有特殊指定努溃,默認(rèn)采用延
    遲初始化策略(lazy-load)。
  • ApplicationContext 阻问。 ApplicationContext 在 BeanFactory 的基礎(chǔ)上構(gòu)建梧税,是相對(duì)比較高
    級(jí)的容器實(shí)現(xiàn),除了擁有 BeanFactory 的所有支持称近, ApplicationContext 還提供了其他高級(jí)特性第队,比如事件發(fā)布、國(guó)際化信息支持等 刨秆,在該類型容器啟動(dòng)之后凳谦,默認(rèn)全部初始化并綁定完成。所以衡未,相對(duì)于 BeanFactory 來(lái)
    說(shuō)尸执, ApplicationContext 要求更多的系統(tǒng)資源家凯,同時(shí),因?yàn)樵趩?dòng)時(shí)就完成所有初始化如失,容
    器啟動(dòng)時(shí)間較之 BeanFactory 也會(huì)長(zhǎng)一些绊诲。在那些系統(tǒng)資源充足,并且要求更多功能的場(chǎng)景中褪贵,
    ApplicationContext 類型的容器是比較合適的選擇掂之。

3. BeanFactory 的對(duì)象注冊(cè)與依賴綁定方式

直接編碼

BeanFactory 、 BeanDefinitionRegistry 以及 DefaultListableBeanFactory 的關(guān)系
  • BeanFactory 定義獲取bean及bean的各種屬性脆丁,各個(gè) BeanFactory 的具體實(shí)現(xiàn)類負(fù)責(zé)具體Bean的注冊(cè)以及管理工作
  • BeanDefinition 每個(gè)bean 都有一個(gè)BeanDefinition 對(duì)應(yīng)世舰,保存對(duì)象的所有必要信息,包括其對(duì)應(yīng)的對(duì)象的class類型槽卫、是否是抽象
    類跟压、構(gòu)造方法參數(shù)以及其他屬性等
  • BeanDefinitionRegistry 定義對(duì)BeanDefinition的各種增刪改操作

外部配置文件方式

  • Properties文件格式
  • XML文件格式
  • 如果需要可以引入自己的文件格式

注解方式

  • 版本要求:Spring 2.5以及Java 5
    或者更高版本的情況之下

4. bean 的 scope (面試:spring bean 支持哪幾種scope/作用域 )

<bean id="mockObject2" class="...MockBusinessObject"
scope="prototype"/>

scope 取值

  • singleton

    • 對(duì)象實(shí)例數(shù)量: 一個(gè) 所有對(duì)該對(duì)象的引用將共享這個(gè)實(shí)例
    • 生命周期: 從容器啟動(dòng),第一請(qǐng)求而初始化以后晒夹,將一直存活到容器退出
  • prototype

    • 對(duì)象實(shí)例數(shù)量:多個(gè) 容器在接到該類型對(duì)象的請(qǐng)求的時(shí)候裆馒,會(huì)每次都重新生成一個(gè)新的對(duì)象實(shí)例給請(qǐng)求方
    • 生命周期: 對(duì)象的實(shí)例化以及屬性設(shè)置等工作由容器負(fù)責(zé)的姊氓,但是只要準(zhǔn)備完畢丐怯,并且對(duì)象實(shí)例返回給請(qǐng)求方之后,容器就不再擁有當(dāng)前返回對(duì)象的引用翔横,請(qǐng)求方需要自己負(fù)責(zé)當(dāng)前返回對(duì)象的后繼生命周期的管理工作读跷,包括該對(duì)象的銷毀
  • request

    • 對(duì)象實(shí)例數(shù)量: 多個(gè) 每個(gè)HTTP請(qǐng)求創(chuàng)建一個(gè)全新的 RequestProcessor 對(duì)象供當(dāng)前請(qǐng)求使用
    • 生命周期: 當(dāng)請(qǐng)求結(jié)束后,該對(duì)象實(shí)例的生命周期即告結(jié)束
<bean id="requestProcessor" class="...RequestProcessor"
scope="request"/>
  • session
    • 對(duì)象實(shí)例數(shù)量: 多個(gè) 每個(gè)獨(dú)立的session創(chuàng)建屬于它們自己的全新的 UserPreferences 對(duì)象實(shí)例
    • 生命周期: session的生命周期
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

  • global session
    • 對(duì)象實(shí)例數(shù)量:
    • 生命周期: portlet的Web應(yīng)用程序中才有意義禾唁,它映射到portlet的global范圍的
      session, 如果在普通的基于servlet的Web應(yīng)用中使用了這個(gè)類型的scope效览,容器會(huì)將其作為普通的session
      類型的scope對(duì)待
<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>
  • 自定義 scope ,可以根據(jù)自己的需要或者應(yīng)用的場(chǎng)景,來(lái)添加自定義的scope類型

5. BeanFactoryPostProcessor

  • 作用: 允許我們?cè)谌萜鲗?shí)
    例化相應(yīng)對(duì)象之前荡短,對(duì)注冊(cè)到容器的 BeanDefinition 所保存的信息做相應(yīng)的修改丐枉。,讓我們對(duì)最終的 BeanDefinition 做一些額外的操作掘托,比如修
    改其中bean定義的某些屬性瘦锹,為bean定義增加其他信息等 例如 我們使用占位符配置數(shù)據(jù)庫(kù)相關(guān)信息,然后通過(guò)配置文件 配置實(shí)際的值闪盔。

6. bean的生命周期

graph TB
實(shí)例化bean對(duì)象-->設(shè)置對(duì)象屬性
設(shè)置對(duì)象屬性-->檢查Aware相關(guān)接口并設(shè)置相關(guān)依賴
檢查Aware相關(guān)接口并設(shè)置相關(guān)依賴-->beanPostProcessor前置處理
beanPostProcessor前置處理-->檢查是否是InitializingBean以決定是否調(diào)用afterPropertiesSet
檢查是否是InitializingBean以決定是否調(diào)用afterPropertiesSet-->檢查是否配置有自定義init-method
檢查是否配置有自定義init-method-->beanPostProcessor后置處理
beanPostProcessor后置處理-->注冊(cè)必要的Destruction相關(guān)回調(diào)接口
注冊(cè)必要的Destruction相關(guān)回調(diào)接口-->使用中
使用中-->是否實(shí)現(xiàn)DisPosableBean接口
是否實(shí)現(xiàn)DisPosableBean接口-->是否配置有自定義的destory方法

6.1 實(shí)例化bean對(duì)象弯院,設(shè)置對(duì)象屬性

  • 容器在內(nèi)部實(shí)現(xiàn)的時(shí)候,采用“策略模式(Strategy Pattern)”來(lái)決定采用何種方式初始化bean實(shí)例泪掀。
    通常听绳,可以通過(guò)反射或者CGLIB動(dòng)態(tài)字節(jié)碼生成來(lái)初始化相應(yīng)的bean實(shí)例或者動(dòng)態(tài)生成其子類
  • 容器根據(jù)BeanDefintion 取得實(shí)例化信息,結(jié)合CglibSubclassingInstantiationStrategy策略以及不同的bean定義類型异赫,就可以返回實(shí)例化完成的對(duì)象實(shí)例
    • 根據(jù)beandefinition 有沒有l(wèi)ookup-override或者replace-override屬性 判斷是否用 cglib策略
  • 返回 BeanWrapper 對(duì)構(gòu)造完成的對(duì)象實(shí)例進(jìn)行包裹椅挣,返回相應(yīng)的 BeanWrapper 實(shí)例
  • 通過(guò)BeanWrapper設(shè)置對(duì)象屬性头岔,免去直接使用Java反射API,java反射很多異常要處理

6.2 檢查Aware相關(guān)接口并設(shè)置相關(guān)依賴

  • 當(dāng)對(duì)象實(shí)例化完成并且相關(guān)屬性以及依賴設(shè)置完成之后鼠证,Spring容器會(huì)檢查當(dāng)前對(duì)象實(shí)例是否實(shí)
    現(xiàn)了一系列的以 Aware 命名結(jié)尾的接口定義切油。如果是,則將這些 Aware 接口定義中規(guī)定的依賴注入給當(dāng)前對(duì)象實(shí)例名惩。
    • org.springframework.beans.factory.BeanNameAware 澎胡。如果Spring容器檢測(cè)到當(dāng)前對(duì)象實(shí)
      例實(shí)現(xiàn)了該接口,會(huì)將該對(duì)象實(shí)例的bean定義對(duì)應(yīng)的 beanName 設(shè)置到當(dāng)前對(duì)象實(shí)例娩鹉。
    • org.springframework.beans.factory.BeanClassLoaderAware 攻谁。如果容器檢測(cè)到當(dāng)前對(duì)
      象實(shí)例實(shí)現(xiàn)了該接口,會(huì)將 對(duì)應(yīng)加載當(dāng)前 bean的Classloader注入當(dāng)前對(duì)象實(shí)例弯予。默認(rèn)會(huì)使用
      加載org.springframework.util.ClassUtils類的Classloader戚宦。
    • org.springframework.beans.factory.BeanFactoryAware 。在介紹方法注入的時(shí)候锈嫩,我們
      提到過(guò)使用該接口以便每次獲取prototype類型bean的不同實(shí)例受楼。如果對(duì)象聲明實(shí)現(xiàn)了
      BeanFactoryAware 接口, BeanFactory 容器會(huì)將自身設(shè)置到當(dāng)前對(duì)象實(shí)例呼寸。這樣艳汽,當(dāng)前對(duì)象
      實(shí)例就擁有了一個(gè) BeanFactory 容器的引用,并且可以對(duì)這個(gè)容器內(nèi)允許訪問(wèn)的對(duì)象按照需要
      進(jìn)行訪問(wèn)对雪。
    • ApplicationContext 很多 Aware 接口通過(guò)BeanPostProcessor 實(shí)現(xiàn) 如下ApplicationContextAwareProcessor的postProcessBeforeInitialization方法
package org.springframework.context.support;
class ApplicationContextAwareProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
        if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    ApplicationContextAwareProcessor.this.invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        } else {
            this.invokeAwareInterfaces(bean);
        }

        return bean;
    }
}

6.3 beanPostProcessor

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;

    Object postProcessAfterInitialization (Object var1, String var2) throws BeansException;
}
  • postProcessBeforeInitialization 前置處理
  • postProcessAfterInitialization 后置處理
  • 可以自定義beanPostProcessor 處理
    public class PasswordDecodePostProcessor implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object object, String beanName)
    throws BeansException {
    return object;
    }
    public Object postProcessBeforeInitialization(Object object, String beanName)
    throws BeansException {
    if(object instanceof 我們想要處理的bean.class)
    {
     // 設(shè)置屬性河狐,加密解密等。
    }
    return object;
    }

}


6.4 InitializingBean瑟捣,init-method

package org.springframework.beans.factory;
public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}
  • InitializingBean
    • 作用: 在對(duì)象實(shí)例化過(guò)程調(diào)用過(guò)“ BeanPostProcessor 的前置處理”
      之后馋艺,會(huì)接著檢測(cè)當(dāng)前對(duì)象是否實(shí)現(xiàn)了 InitializingBean 接口,如果是迈套,則會(huì)調(diào)用其 afterPropertiesSet() 方法進(jìn)一步調(diào)整對(duì)象實(shí)例的狀態(tài)捐祠。
    • 場(chǎng)景: 在有些情況下,某個(gè)業(yè)務(wù)對(duì)象實(shí)例化完成后桑李,還
      不能處于可以使用狀態(tài)踱蛀。這個(gè)時(shí)候就可以讓該業(yè)務(wù)對(duì)象實(shí)現(xiàn)該接口,并在方法 afterPropertiesSet()
      中完成對(duì)該業(yè)務(wù)對(duì)象的后續(xù)處理 如圖片驗(yàn)證碼攔截器 在實(shí)例化之后芙扎,通過(guò)afterPropertiesSet 從配置中讀取要攔截的路徑
  • init-method
    • 作用: 自定義初始化操作可以以任何方式命名星岗,還可以通
      過(guò)最頂層的 <beans> 的 default-init-method 統(tǒng)一指定。
    • 場(chǎng)景: InitializingBean 一樣
  • 對(duì)比:InitializingBean 業(yè)務(wù)對(duì)象實(shí)現(xiàn)這個(gè)接口戒洼,有侵入性 init-method 就沒有這個(gè)問(wèn)題

6.5 注冊(cè)必要的Destruction(一次性)相關(guān)回調(diào)接口

  • bean 使用前還有注冊(cè)一些相關(guān)回調(diào)接口

6.6 DisposableBean俏橘,destroy-method

package org.springframework.beans.factory;

public interface DisposableBean {
    void destroy() throws Exception;
}
  • 作用: 為該實(shí)例注冊(cè)一個(gè)用于對(duì)象銷毀的回調(diào)(Callback),以便在這些singleton類型的對(duì)象實(shí)例銷毀之
    前圈浇,執(zhí)行銷毀邏輯寥掐。只有該對(duì)象實(shí)例不再被使用的時(shí)候靴寂,
    才會(huì)執(zhí)行相關(guān)的自定義銷毀邏輯,此時(shí)通常也就是Spring容器關(guān)閉的時(shí)候
  • 執(zhí)行對(duì)象的自定義銷毀方法
    • BeanFactory destroySingletons()
    • ApplicationContext registerShutdownHook() 使用了addShutdownHook()
//m中增加一個(gè)關(guān)閉的鉤子召耘,當(dāng)jvm關(guān)閉的時(shí)候百炬,會(huì)執(zhí)行系統(tǒng)中已經(jīng)設(shè)置的所有通過(guò)方法addShutdownHook添加的鉤子,當(dāng)系統(tǒng)執(zhí)行完這些鉤子后污它,jvm才會(huì)關(guān)閉剖踊。所以這些鉤子可以在jvm關(guān)閉的時(shí)候進(jìn)行內(nèi)存清理、對(duì)象銷毀等操作衫贬。
Runtime.getRuntime().addShutdownHook(Thread hook)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末德澈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子固惯,更是在濱河造成了極大的恐慌梆造,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葬毫,死亡現(xiàn)場(chǎng)離奇詭異镇辉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)贴捡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門忽肛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人栈暇,你說(shuō)我怎么就攤上這事麻裁」烤担” “怎么了源祈?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)色迂。 經(jīng)常有香客問(wèn)我香缺,道長(zhǎng),這世上最難降的妖魔是什么歇僧? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任图张,我火速辦了婚禮,結(jié)果婚禮上诈悍,老公的妹妹穿的比我還像新娘祸轮。我一直安慰自己,他們只是感情好侥钳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布适袜。 她就那樣靜靜地躺著,像睡著了一般舷夺。 火紅的嫁衣襯著肌膚如雪苦酱。 梳的紋絲不亂的頭發(fā)上售貌,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音疫萤,去河邊找鬼颂跨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛扯饶,可吹牛的內(nèi)容都是我干的恒削。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼尾序,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蔓同!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蹲诀,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤斑粱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后脯爪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體则北,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年痕慢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尚揣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掖举,死狀恐怖快骗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情塔次,我是刑警寧澤方篮,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站励负,受9級(jí)特大地震影響藕溅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜继榆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一巾表、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧略吨,春花似錦集币、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春偶妖,著一層夾襖步出監(jiān)牢的瞬間姜凄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工趾访, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留态秧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓扼鞋,卻偏偏與公主長(zhǎng)得像申鱼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子云头,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 2.1 我們的理念是:讓別人為你服務(wù) IoC是隨著近年來(lái)輕量級(jí)容器(Lightweight Container)的...
    好好學(xué)習(xí)Sun閱讀 2,705評(píng)論 0 11
  • 1- IOC的概念 IOC:也即控制反轉(zhuǎn)捐友,DI即依賴注入,控制反轉(zhuǎn)IOC和依賴注入DI其實(shí)就是同個(gè)概念的兩個(gè)不同...
    zhanglbjames閱讀 3,005評(píng)論 1 3
  • 一溃槐、自定義bean的生命周期 通過(guò)實(shí)現(xiàn)spring的InitializingBean和DisposableBean...
    夏與清風(fēng)閱讀 938評(píng)論 0 1
  • 1.概念 控制反轉(zhuǎn) 對(duì)于軟件來(lái)說(shuō)匣砖,調(diào)用類依賴于某一接口的實(shí)現(xiàn)類。但是現(xiàn)在將控制權(quán)從調(diào)用類移除昏滴,轉(zhuǎn)而由第三方?jīng)Q定猴鲫,即...
    小螺釘12138閱讀 252評(píng)論 2 0
  • 猶憶杏花雨,清明淚幾行谣殊。 墳頭多嫩柳拂共,陌上斷人腸。 綠暗鳴蜩樂姻几,紅酣落日傷宜狐。 經(jīng)年歸不得,自是念爺娘蛇捌。
    林香砌閱讀 216評(píng)論 0 11