spring專題系列之IOC的理解和分析

根據(jù)時間安排迷郑,今天主要是對spring中IOC的理解躯砰。對于IOC的理解可以從以下幾個角度去分析每币。

  • 什么是IOC?如何使用案例來理解琢歇?
  • IOC有哪幾種實(shí)現(xiàn)方式兰怠?
  • IOC的底層實(shí)現(xiàn)過程是什么?

根據(jù)這幾個角度李茫,開始今天的故事揭保,

1 什么是IOC?

對于IOC的理解魄宏,主要是停留在概念和幾種注入的方式上秸侣,雖然知道其生命周期,但是對整個bean管理的宏觀角度娜庇,理解的不夠深刻塔次。

IOC:控制反轉(zhuǎn)(Inversion of Control)容器,是一種設(shè)計(jì)思想名秀。意味著將你設(shè)計(jì)好的對象交給容器控制励负。

1.1 什么是依賴注入

這個概念的理解,我準(zhǔn)備使用一個案例來表示匕得。如果a類中包含了b類继榆,就說明a類對b類產(chǎn)生了依賴。如一個人需要車汁掠,這就說人對車產(chǎn)生了依賴略吨。

class User{ 
  Car car; 
  public User(){ 
    car=new Car(); 
  } 
}

上面這個案例,可以看到考阱,在User類中翠忠,包含了Car類,也就說User類對Car類產(chǎn)生了依賴乞榨。

按照傳統(tǒng)的方式秽之,User類如果想要使用Car基本上就是在內(nèi)部new一個新對象即可。但是這樣做缺點(diǎn)很大吃既,new的方式也就意味著User和Car產(chǎn)生了緊耦合考榨。不利于大規(guī)模使用。于是使用了另外一種方式可以代替鹦倚。那就是什么時候用到Car河质,從外部直接傳遞過來就好。這樣的話,耦合性就大大降低了掀鹅。再看下面這種形式是不是就好很多了散休。

class User{ 
  Car car; 
  public User(Car car){ 
    this.car=car; 
  } 
}

像這樣的方式就是依賴注入,也就是把依賴Car注入到了User中淫半。

1.2 什么是控制反轉(zhuǎn)

有了上面依賴注入的概念溃槐,再立即控制反轉(zhuǎn)就比較簡單了。

  • 誰控制誰:傳統(tǒng)方式User是在內(nèi)部new科吭,現(xiàn)在我們通過依賴注入的方式注入依賴對象Car』璧危現(xiàn)在spring出現(xiàn)了,發(fā)明了IOC对人,IOC里面有一個容器谣殊,這些依賴對象全部交給容器去管理。也就是說這些依賴對象的控制權(quán)交給了容器牺弄。

  • 如何反轉(zhuǎn):傳統(tǒng)方式User是主動去new姻几,這種方式是正轉(zhuǎn)。反轉(zhuǎn)是由容器來幫忙創(chuàng)建及注入依賴對象势告;

2 依賴注入的幾種形式

目前主要有五種注入方式:SET注入蛇捌,構(gòu)造器注入,靜態(tài)工廠咱台,實(shí)例工廠络拌。

本文直接使用網(wǎng)上的基本案例來實(shí)現(xiàn)。比如UserService依賴UserDao回溺。先把UserDao定義好了春贸,接下來看如何實(shí)現(xiàn)注入的。

public class UserDao {
    public String userLogin() {
        return  "userLogin()方法";
    }
}

下面看幾種依賴注入的幾種實(shí)現(xiàn)方式遗遵。

2.1 set注入

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="userDao" class="com.xxx.demo.UserDao"></bean>
    <!-- setter注入 -->
    <bean id="userService" class="com.xxx.demo.UserService">
        <!--ref是對于外部bean對象引用萍恕,與被引用的bean對象的id保持一致-->
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>

第二步:set方式注入

public class UserService {
    //一定要提供屬性的setter方法
    private UserDao userDao;
    public void userlogin() {
        String res=userDao.userLogin();
        System.out.println(res);
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

這種方式簡單易操作。

2.2 構(gòu)造器注入

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="userDao" class="com.xxx.demo.UserDao"></bean>
    <!-- 構(gòu)造器注入 -->
    <bean id="userServiceV2" class="com.xxx.demo.UserServiceV2">
        <constructor-arg index="0" ref="userDao"></constructor-arg>
        <constructor-arg index="1" value="印度三哥"></constructor-arg>
    </bean>
</beans>

第二步:構(gòu)造器注入

public class UserServiceV2 {
    private UserDao userDao;
    private String name;
    public void userlogin() {
        String res=userDao.userLogin();
        System.out.println(res);
        System.out.println(name);
    }
    public UserServiceV2(UserDao userDao,String name) {
        super();
        this.userDao = userDao;
        this.name = name;
    }
}

2.3 靜態(tài)工廠注入

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 靜態(tài)工廠注入 -->
    <bean id="userDao01" class="com.xxx.demo.StaticFactory" factory-method="createuserDao"></bean>
    <bean id="userService01" class="com.xxx.demo.UserService">
        <property name="userDao" ref="userDao01"></property>
    </bean>
</beans>

第二步:定義靜態(tài)工廠

public class StaticFactory {
    public static UserDao createuserDao(){
        return new UserDao();
    }
}

第三部:靜態(tài)工廠注入

public class UserService {
    private UserDao userDao;
    public void userlogin() {
        String res=userDao.userLogin();
        System.out.println(res);
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

2.4 實(shí)例化工廠

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 實(shí)例化工廠 -->
    <bean id="instanceFactory" class="com.xxx.demo.InstanceFactory"></bean>
    <bean id="userDao3" factory-bean="instanceFactory" factory-method="createUserDao"></bean>
    <bean id="userService02" class="com.xxx.demo.UserService">
        <property name="userDao" ref="userDao3"></property>
    </bean>
</beans>

第二步:工廠注入

public class InstanceFactory {
    public UserDao createUserDao(){
        return new UserDao();
    }
}

以上就是幾種常見的注入方式车要。在開發(fā)中比較常用允粤。知道了IOC的概念和幾種實(shí)現(xiàn)方式之后,下面主要探討IOC的底層實(shí)現(xiàn)原理翼岁。

3 IOC底層實(shí)現(xiàn)過程

以上的幾種注入方式维哈,可能有個疑問,那就是bean是如何從xml登澜,再到注入類中的呢?看下面這張圖

核心原理.png

Spring IOC容器初始化的核心過程主要有四個步驟(還有一些如:后置加載器飘庄,國際化脑蠕,事件廣播器等一些過程不展開):

  1. Bean定義的定位,Bean 可能定義在XML中,或者一個注解谴仙,或者其他形式迂求。這些都被用Resource來定位,讀取Resource獲取BeanDefinition 注冊到 Bean定義注冊表中晃跺。
  2. 第一次向容器getBean操作會觸發(fā)Bean的創(chuàng)建過程,實(shí)列化一個Bean時 ,根據(jù)BeanDefinition中類信息等實(shí)列化Bean揩局。
  3. 將實(shí)列化的Bean放到單列Bean緩存內(nèi)。
  4. 此后再次獲取向容器getBean就會從緩存中獲取掀虎。

這張圖是核心的過程凌盯。這個過程是已經(jīng)簡化了,具體的實(shí)現(xiàn)方式要設(shè)計(jì)到bean的生命周期的管理烹玉。安排到下一章節(jié)了驰怎。
spring的核心內(nèi)容就是aop和ioc,知道了這倆是如何實(shí)現(xiàn)的之后二打,就是核心bean管理的核心實(shí)現(xiàn)县忌,最后對配置文件進(jìn)行介紹。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末继效,一起剝皮案震驚了整個濱河市症杏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑞信,老刑警劉巖厉颤,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異喧伞,居然都是意外死亡走芋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門潘鲫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翁逞,“玉大人,你說我怎么就攤上這事溉仑⊥诤” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵浊竟,是天一觀的道長怨喘。 經(jīng)常有香客問我,道長振定,這世上最難降的妖魔是什么必怜? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮后频,結(jié)果婚禮上梳庆,老公的妹妹穿的比我還像新娘暖途。我一直安慰自己,他們只是感情好膏执,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布驻售。 她就那樣靜靜地躺著,像睡著了一般更米。 火紅的嫁衣襯著肌膚如雪欺栗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天征峦,我揣著相機(jī)與錄音迟几,去河邊找鬼。 笑死眶痰,一個胖子當(dāng)著我的面吹牛瘤旨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竖伯,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼存哲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了七婴?” 一聲冷哼從身側(cè)響起祟偷,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎打厘,沒想到半個月后修肠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡户盯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年嵌施,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莽鸭。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡吗伤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出硫眨,到底是詐尸還是另有隱情足淆,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布礁阁,位于F島的核電站巧号,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏姥闭。R本人自食惡果不足惜丹鸿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棚品。 院中可真熱鬧卜高,春花似錦弥姻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疼进。三九已至薪缆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伞广,已是汗流浹背拣帽。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嚼锄,地道東北人减拭。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像区丑,于是被迫代替她去往敵國和親拧粪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

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