一. 什么是IoC
1. 什么是耦合和內(nèi)聚
- 耦合指的就是模塊之間的依賴關(guān)系。模塊間的依賴越多称勋,則表示耦合度越高胸哥,相應(yīng)的維護(hù)成本就越高。
- 內(nèi)聚指的是模塊內(nèi)功能之間的聯(lián)系赡鲜。模塊內(nèi)功能的聯(lián)系越緊密空厌,則表示內(nèi)聚度越高,模塊的職責(zé)也就越單一银酬。
所以在程序開發(fā)中應(yīng)該盡量的降低耦合嘲更,提高內(nèi)聚。也就是設(shè)計(jì)原則中的開閉原則和單一職責(zé)原則揩瞪。
2. 工廠模式
工廠模式就是用來解決程序間耦合的一種設(shè)計(jì)模式赋朦。可以把所有要?jiǎng)?chuàng)建的對(duì)象放在工廠的一個(gè)集合里李破,當(dāng)需要使用這個(gè)對(duì)象的時(shí)候宠哄,直接從工廠里面取出來用就行。
工廠模式的優(yōu)點(diǎn):
- 一個(gè)調(diào)用者想創(chuàng)建一個(gè)對(duì)象嗤攻,只需要指定相應(yīng)的名字即可從工廠中獲得這個(gè)對(duì)象毛嫉。
- 屏蔽了產(chǎn)品的具體實(shí)現(xiàn),調(diào)用者只關(guān)心產(chǎn)品的接口妇菱。
3. 控制反轉(zhuǎn)(IoC)
控制反轉(zhuǎn)在維基百科中的定義:
控制反轉(zhuǎn)(Inversion of Control承粤,縮寫為IoC),是面向?qū)ο缶幊讨械囊环N設(shè)計(jì)原則闯团,可以用來減低計(jì)算機(jī)代碼之間的耦合度辛臊。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI)偷俭,還有一種方式叫“依賴查找”(Dependency Lookup)浪讳。通過控制反轉(zhuǎn),對(duì)象在被創(chuàng)建的時(shí)候涌萤,由一個(gè)調(diào)控系統(tǒng)內(nèi)所有對(duì)象的外界實(shí)體淹遵,將其所依賴的對(duì)象的引用傳遞(注入)給它。
下面再從控制和反轉(zhuǎn)兩個(gè)詞分兩個(gè)方面來理解:
- 誰控制誰负溪?IoC容器控制了對(duì)象透揣。控制什么川抡?控制了對(duì)象要獲取的外部資源(其它對(duì)象或數(shù)據(jù)等)
- 什么是反轉(zhuǎn)辐真?是IoC容器查找并注入依賴給對(duì)象须尚,對(duì)象是被動(dòng)的接受,而不是主動(dòng)的創(chuàng)建侍咱,所以是反轉(zhuǎn)耐床。
通過new方式來主動(dòng)獲取對(duì)象:
通過IoC容器獲取對(duì)象(注意看箭頭的方向撩轰,是不是反轉(zhuǎn)了):
有了IoC容器后堪嫂,把創(chuàng)建和查找依賴對(duì)象的控制權(quán)交給了容器,由容器進(jìn)行注入組合對(duì)象木柬,所以對(duì)象與對(duì)象之間是松散耦合皆串,這樣也方便測試,利于功能復(fù)用眉枕,更重要的是使得程序的整個(gè)體系結(jié)構(gòu)變得非常靈活恶复。
4. 依賴注入(DI)
依賴注入在維基百科中的定義
在軟件工程中,依賴注入是種實(shí)現(xiàn)控制反轉(zhuǎn)用于解決依賴性設(shè)計(jì)模式齐遵。一個(gè)依賴關(guān)系指的是可被利用的一種對(duì)象(即服務(wù)提供端) 寂玲。依賴注入是將所依賴的傳遞給將使用的從屬對(duì)象(即客戶端)塔插。該服務(wù)是將會(huì)變成客戶端的狀態(tài)的一部分梗摇。傳遞服務(wù)給客戶端,而非允許客戶端來建立或?qū)ふ曳?wù)想许,是本設(shè)計(jì)模式的基本要求伶授。
其實(shí)依賴注入和控制反轉(zhuǎn)表達(dá)的是一個(gè)意思×魑疲控制反轉(zhuǎn)是一種思想糜烹,而依賴注入是這個(gè)思想的最典型的實(shí)現(xiàn)方法。
由IoC來控制對(duì)象的依賴漱凝,通過構(gòu)造函數(shù)疮蹦、變量或Setter等方法來將依賴注入到對(duì)象中,這樣就將對(duì)象和對(duì)象的依賴進(jìn)行了解耦茸炒。
二. spring中的工廠類
我們常用的spring容器是ApplicationContext愕乎,先來看一下它的依賴結(jié)構(gòu)。
由圖可知,spring容器中的頂層接口是BeanFactory紊册。ApplicationContext是它的子接口(注意這個(gè)也是個(gè)接口哦)比肄。它默認(rèn)一讀取配置文件,就會(huì)創(chuàng)建對(duì)象放到容器中。再來看一下ApplicationContext的三個(gè)主要的實(shí)現(xiàn)類芳绩。
- ClassPathXmlApplication:它是從類的根路徑下加載xml配置文件(推薦用這種)妥色。
- FileSystemXmlApplication: 它是從磁盤路徑上加載配置文件铺浇,配置文件可以在磁盤的任意位置。(但使用不靈活垛膝,不推薦)
- AnnotationConfigApplication:當(dāng)我們使用注解配置容器對(duì)象時(shí)鳍侣,需要使用此類來創(chuàng)建spring容器。它用來讀取注解吼拥。(springboot默認(rèn)使用這個(gè))
三. Bean的創(chuàng)建和管理
1. bean標(biāo)簽
作用 : 用于配置對(duì)象讓spring來創(chuàng)建的倚聚。默認(rèn)情況下它調(diào)用的是類中的無參構(gòu)造函數(shù)。如果沒有無參構(gòu)造函數(shù)則不能創(chuàng)建成功凿可。
屬性:
id:給對(duì)象在容器中提供一一個(gè)唯一 標(biāo)識(shí)惑折。用于獲取對(duì)象。
class:指定類的全限定類名枯跑。用于反射創(chuàng)建對(duì)象惨驶。默認(rèn)情況下調(diào)用無參構(gòu)造函數(shù)。
scope:指定對(duì)象的作用范圍敛助。
singleton : 單例對(duì)象粗卜,也是默認(rèn)的。
prototype : 多例對(duì)象纳击,每次都創(chuàng)建一個(gè)不同的對(duì)象续扔。
request :WEB 項(xiàng)目中,Spring創(chuàng)建一個(gè)Bean的對(duì)象焕数,將對(duì)象存入到request域中.
session : WEB項(xiàng)目中纱昧,Spring創(chuàng)建一個(gè)Bean的對(duì)象,將對(duì)象存入到session域中堡赔。
global session:WEB項(xiàng)目中识脆,應(yīng)用在集群環(huán)境.如果沒有集群環(huán)境那么globalSession相當(dāng)于session.
init-method:指定類中的初始化方法名稱。
destroy-method:指定類中銷毀方法名稱善已。
2. bean的作用范圍和生命周期
①. 單例對(duì)象: scope="singleton"一個(gè)應(yīng)用只有一一個(gè)對(duì)象的實(shí)例灼捂。它的作用范圍就是整個(gè)引用。生命周期:
- 對(duì)象出生:當(dāng)應(yīng)用加載雕拼,創(chuàng)建容器時(shí)纵东,對(duì)象就被創(chuàng)建了。
- 對(duì)象活著:只要容器在啥寇,對(duì)象-直活著偎球。
- 對(duì)象死亡:當(dāng)應(yīng)用卸載洒扎,銷毀容器時(shí),對(duì)象就被銷毀了衰絮。
②. 多例對(duì)象: scope="prototype"每次訪問對(duì)象時(shí)袍冷,都會(huì)重新創(chuàng)建對(duì)象實(shí)例。生命周期:
- 每次訪問對(duì)象時(shí)猫牡,都會(huì)重新創(chuàng)建對(duì)象實(shí)例胡诗。
- 對(duì)象活著:只要對(duì)象在使用中,就一直活著淌友。
- 對(duì)象死亡:由java的垃圾回收器機(jī)制來處理煌恢。
四. spring中的注解
1. 用于創(chuàng)建對(duì)象的
相當(dāng)于<bean id = "" class = "" />
①. @component
- 作用:把資源讓spring來管理,相當(dāng)于在xml中注冊(cè)一個(gè)bean震庭。
- 屬性:value:指定bean的id.如果不指定value屬性瑰抵,默認(rèn)bean的id是當(dāng)前類的類名。首字母小寫器联。
②.@Service 二汛、@Repository 、@Controller他們都是對(duì)@Component注解的衍生拨拓,其實(shí)作用是一模一樣的肴颊,只是提供了更明確的語義化。
- @Repository:一般用于持久層的注解渣磷。
- @Service:一般用于業(yè)務(wù)層的注解
- @Controller:一般用于表現(xiàn)層的注解婿着。
2. 用于注入數(shù)據(jù)的
相當(dāng)于<property name = "" ref = "" /> 或 <property name= "" value = "" />
①. @Autowried
作用:自動(dòng)按照類型注入。當(dāng)使用注解注入屬性時(shí)幸海,set 方法可以省略祟身。它只能注入其他bean類型(ByType)奥务。當(dāng)有多個(gè)類型匹配時(shí)物独,使用要注入的對(duì)象變量名稱作為bean的id (ByName) ,在spring容器查找,找到了也可以注入成功氯葬。找不到就報(bào)錯(cuò)挡篓。
三種注入方式(屬性輸入、Setter注入帚称、構(gòu)造函數(shù)注入):
/** * 使用變量注入依賴 */@Autowiredprivate IAccountDao accountDao ;/** * 使用構(gòu)造器注入 spring推薦使用這個(gè) * @param accountDao 要注入的依賴 */@Autowiredpublic AccountServiceImpl(IAccountDao accountDao) { this.accountDao = accountDao;}/** * 使用Setter注入 * @param accountDao 要注入的依賴 */@Autowiredpublic void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao;}
②. @Qualifier
- 作用:在自動(dòng)按照類型注入的基礎(chǔ)之上官研,再按照Bean的id注入。它在給字段注入時(shí)不能獨(dú)立使用闯睹,必須和@Autowire一起使用;但是給方法參數(shù)注入時(shí)戏羽,可以獨(dú)立使用。
- 屬性:value:指定bean的id.
③. @Resource
- 作用:@Resource采用 name 屬性楼吃。默認(rèn)情況下始花,Spring 將 value 解釋為要注入的 bean name妄讯。也就是ByName注入。
- 屬性:value:指定bean的id.
④. @Value
- 作用:用于注入基本類型數(shù)據(jù)和String類型數(shù)據(jù)
- 屬性:用于指定值酷宵,可使用SpEL表達(dá)式亥贸。
3. 用于改變作用域的
相當(dāng)于<bean id = "" class = "" scope = ""/>中的scope屬性
①. @Scope
- 作用:指定bean的作用范圍。
- 屬性:value:指定bean的作用范圍浇垦。取值: singleton prototype request session globalsession炕置。
4. 生命周期相關(guān)的
相當(dāng)于<bean id = "" class = "" init-method = "" destory-method = ""/>中的init-method屬性和destory-method屬性
①. @PostConstruct
作用:用于指定初始化方法
②. @PostDestory
作用:用于指定銷毀方法
5. spring中的新注解
①. @Configuration
- 作用:用于指定當(dāng)前類是一個(gè)spring配置類,當(dāng)創(chuàng)建容器時(shí)會(huì)從該類上加載注解男韧。獲取容器時(shí)需要使用AnnotationApplicationContext (有@Configuration注解的類. class)朴摊。
- 屬性:value:用于指定配置類的字節(jié)碼
②. @ComponentScan
- 作用:用于指定spring在初始化容器時(shí)要掃描的包。作用和在spring的xml配置文件中的<context : component-scan base-package="com. itheima"/>是一樣的此虑。
- 屬性:basePackages: 用于指定要掃描的包仍劈。和該注解中的value屬性作用一樣。
③. Bean
- 作用:該注解只能寫在方法(該方法的返回值作為bean放到容器中)上寡壮,表明使用此方法創(chuàng)建一個(gè)對(duì)象贩疙, 并且放入spring容器。
- 屬性:name:給當(dāng)前@Bean注解方法創(chuàng)建的對(duì)象指定一個(gè)名稱 (即bean的id)况既。
④. @PropertySource
- 作用:用于加載.properties文件中的配置这溅。例如我們配置數(shù)據(jù)源時(shí),可以把連接數(shù)據(jù)庫的信息寫到properties配置文件中棒仍,就可以使用此注解指定properties配置文件的位置悲靴。
- 屬性:value[] :用于指定properties文件位置。如果是在類路徑下莫其,需要寫上classpath:癞尚。
示例:
@Configuration@PropertySource("classpath:jdbc.properties")public class JdbcConfig{}
⑤. @Import
- 作用:用于導(dǎo)入其他配置類,在引入其他配置類時(shí)乱陡,可以不用再寫@Configuration注解浇揩。當(dāng)然,寫上也沒問題憨颠。
- 屬性:value[] :用干指定其他配置類的字節(jié)碼胳徽。
示例:
@Configuration@ComponentScan(basePackages = "com.ncusoft.springDemos")@Import({ JdbcConfig.class })public class SpringConfiguration {}
6. 選擇XML還是注解?
先來看一下各自的優(yōu)勢(shì):
- 注解的優(yōu)勢(shì):配置簡單爽彤,維護(hù)方便(我們找到類养盗,就相當(dāng)于找到了對(duì)應(yīng)的配置)。
- XML的優(yōu)勢(shì):修改時(shí)适篙,不用改源碼往核。不涉及重新編譯和部署。
應(yīng)該根據(jù)實(shí)際的開發(fā)來選擇使用(springboot推薦使用注解)嚷节,一般在source code(源代碼)中的類使用注解來創(chuàng)建bean(更方便聂儒,只需一個(gè)注解搞定)蝶缀。從外部引入的依賴可選擇使用XML來創(chuàng)建bean。
來源:微信公眾號(hào)“慕容千語”