白話Spring -- Spring IOC
??筆者雖然看過不少的技術(shù)博客脓恕,也用過Spring寫過一年的代碼衰絮,也修改過BUG练俐,但是還是不理解到底什么是Spring沸久?
??PS:不知道大家有沒有同感季眷,不是技術(shù)博客看不懂,那些個IOC卷胯、AOP也是能看懂子刮,但就是感覺沒有真正的理解透徹,總感覺還是有一層薄霧籠罩著窑睁,從而沒辦法隨心所欲的使用Spring挺峡。
??筆者現(xiàn)在就通過這一系列文章,具象化的担钮、圖形化的說一下我對Spring的理解沙郭,不僅是對大家的一點幫助,也是筆者記錄自己的心得感受裳朋,以免以后忘記了病线。
本文將通過:
- Spring是個啥?
- Spring-IOC是個啥鲤嫡?
- Spring-IOC能干啥送挑?
- 為什么要用Spring?
- Spring怎么使用的暖眼?
這幾點來講解一下我理解中的Spring惕耕。
1. Spring是個啥?
??度娘上和各種博客上都說Spring是一個Java開發(fā)框架诫肠,能方便我們開發(fā)代碼司澎,松耦合,方便實現(xiàn)各種功能栋豫。巴拉巴拉挤安,各種各種。丧鸯。蛤铜。
??等會兒,我們先別管其他的∥Х剩看到能簡化代碼剿干,松耦合。嗯穆刻,這就是Spring置尔。其他的什么框架什么的,管它呢氢伟,等我以后對Spring熟了再說吧榜轿。人臉都沒看清,還指望我能對她能有多深入了解腐芍,對吧差导。
2. Spring-IOC是個啥试躏?
??Spring是一個輕量級的控制反轉(zhuǎn)(IoC)和面向切面(AOP)的容器框架猪勇。
??控制反轉(zhuǎn)——Spring通過一種稱作控制反轉(zhuǎn)(IoC)的技術(shù)促進了松耦合。當應(yīng)用了IoC颠蕴,一個對象依賴的其它對象會通過被動的方式傳遞進來泣刹,而不是這個對象自己創(chuàng)建或者查找依賴對象。你可以認為IoC與JNDI相反——不是對象從容器中查找依賴犀被,而是容器在對象初始化時不等對象請求就主動將依賴傳遞給它椅您。?????--百度百科
??上面是百度百科的解釋,但是看了之后還是一頭霧水寡键。到底啥是IOC掀泳,怎么實現(xiàn)的呢?那么我們就來對比一下吧西轩。
??我們大家以前寫代碼员舵,一個類(Test)要引用另外一個類(Car)都是下面這樣的:
// 代碼塊1
public class Car{
private String name = "蘭博基尼";
public String getCarName(){
return this.name;
}
}
public class Test{
Car car = new Car();
public void test(){
System.out.println("我獲得了一輛" + car.getCarName());
}
}
??我們先理解一下這句話 Car car = new Car();
就是先聲明一個Car
類型的變量:car
,然后再創(chuàng)建一個Car
類型的實例賦值給 car
藕畔,也就是說這個car
只是一個模子马僻,用來存放這個實例的,我們使用的時候直接把car
當成那個實例使用注服。
??大家可能會想這個東西很簡單呀韭邓,為什么還要拿出來再說一遍?放心溶弟,這里我們待會兒就能用到女淑。
??那么,我們來整體理解一下這段代碼辜御,就是Test
類創(chuàng)建了Car
類的實例诗力,并調(diào)用了Car
類的方法。也就是說,Test
類是主動的去創(chuàng)建Car
類的苇本。
??那么袜茧,如果我們使用Spring-IOC呢?
??咱現(xiàn)在還不知道Spring-IOC到底是個啥瓣窄,既然說能幫我們創(chuàng)建實例笛厦,那么咱現(xiàn)在就暫時把Spring-IOC理解成為"哆啦A夢"的百寶囊,我們要什么俺夕,Spring就能提供什么裳凸。
??那么我們接下來的代碼就能這樣寫:
// 代碼塊2
public class Car{
private String name = "蘭博基尼";
public String getCarName(){
return this.name;
}
}
public class Test{
Car car;
//此處假設(shè)Spring可以把實例賦值給car,但具體內(nèi)容暫時忽略劝贸,后面會講
public void test(){
System.out.println("我獲得了一輛" + car.getCarName());
}
}
??大家看到這段代碼肯定一臉懵姨谷。這是啥,怎么變量car
都沒有賦值映九,值為null梦湘,就能調(diào)用方法了?不會報異常嘛件甥。
??大家稍等片刻捌议,別急別急,慢慢來引有。上面的是偽代碼瓣颅,不能被執(zhí)行的。我在這里是先講一下Spring-IOC能給我們做到什么效果譬正。而Spring-IOC也確實可以自己創(chuàng)建一個Car
類實例然后賦值給car
變量宫补。只是這些都是在后臺執(zhí)行的,我們看不到曾我。所以我們在這里就索性認為Spring可以直接給變量賦值實例粉怕。也就是說到這里,car
里就是有實例的您单,不是null斋荞。至于這里的代碼怎么寫,Spring-IOC怎么實現(xiàn)的虐秦,本文的后面會一一講述平酿。
??也就是說:Spring幫助Test
類創(chuàng)建了實例然后又交給了Test
類使用,而不用Test
類自己去創(chuàng)建所需要的實例悦陋。換句話說蜈彼,就是創(chuàng)建Car
類實例的主動權(quán)由Test
類變成了Spring。那么俺驶,我們這里就出現(xiàn)了一個概念:控制反轉(zhuǎn)(IOC):將本來應(yīng)由JavaBean(即Java類)創(chuàng)建實例的主動權(quán)交給了Spring幸逆,讓Spring來創(chuàng)建實例棍辕,再將實例交給JavaBean使用。這種創(chuàng)建實例的控制權(quán)的改變还绘,就稱為控制反轉(zhuǎn)楚昭。
??那么,這玩意兒有啥用拍顷?
3. Spring-IOC能干啥抚太?
??通過上面的代碼塊1-2,我們并不能看出來什么昔案,那么我就新寫一個例子:
??這個例子是兩個類實現(xiàn)了一個接口尿贫,然后實現(xiàn)一種多態(tài)的方式調(diào)用Car
接口的實現(xiàn)類的實例。下面是我們以前的寫法:
//代碼塊3
public interface Car{
public String getCarName();
}
public class BaoShiJie implements Car{
private String name = "保時捷";
public String getCarName(){
return this.name;
}
}
public class FaLaLi implements Car{
private String name = "法拉利";
public String getCarName(){
return this.name;
}
}
public class Test{
Car car = new FaLaLi();
// Car car = new BaoShiJie();
public void test(){
System.out.println("我獲得了一輛" + car.getCarName());
}
}
??從上面可以看出踏揣,如果我們想從"法拉利"改成"保時捷"庆亡,需要修改Test
的代碼,將創(chuàng)建FaLaLi
類的實例修改成創(chuàng)建BaoShiJie
類的實例捞稿。每一次改變都需要修改一次又谋,如此大動干戈,顯然這種方式不太好括享。
??那么搂根,使用Spring-IOC呢珍促?
??我們在代碼塊2中假設(shè)了铃辖,Spring-IOC可以直接給變量賦值實例,那么代碼塊3中的car變量我們是否也可以通過這種方式賦值呢猪叙?有人可能會思考娇斩,即使可以,那程序怎么分辨我們具體要什么車呢穴翩?如此是否我們同樣能假設(shè)我們可以告訴Spring-IOC我們需要哪一輛呢犬第?
// 代碼塊4
public interface Car{
public String getCarName();
}
public class BaoShiJie implements Car{
private String name = "保時捷";
public String getCarName(){
return this.name;
}
}
public class FaLaLi implements Car{
private String name = "法拉利";
public String getCarName(){
return this.name;
}
}
public class Test{
Car car;
// 此處告訴Spring-IOC我需要法拉利/保時捷,假設(shè)Spring-IOC就會把相應(yīng)車的實例賦值給變量car
public void test(){
System.out.println("我獲得了一輛" + car.getCarName());
}
}
??哦哦哦芒帕,出來了歉嗓,大家發(fā)現(xiàn)沒有,Test
類里沒有出現(xiàn)FaLaLi
類或者BaoShiJie
類的身影背蟆,我們告訴Spring-IOC我們需要什么車鉴分,完全可以通過String的方式,如果這個String還是通過外部參數(shù)形式導(dǎo)入的話带膀,那么我們在換車的時候志珍,就完全不同修改Test
類了。