老生常談的話題妻率,所以我這里所說(shuō)的內(nèi)容當(dāng)然不能是一些老掉牙孤里,被人咀嚼了無(wú)數(shù)次的殘?jiān)?/p>
我爭(zhēng)取從一個(gè)特別的角度給你留下別樣的印象∽粮颍現(xiàn)在無(wú)法理解沒(méi)關(guān)系慕淡,只需要記住這些話傻寂,在以后的工作和訓(xùn)練中反復(fù)回味即可携兵。等你悟出自己的道拂檩,歡迎到時(shí)候來(lái)一起討論糠聪。
1. IOC
控制反轉(zhuǎn),一般被和DI混淆丙猬。在我們?cè)噲D明白這些概念前督暂,來(lái)思考下這個(gè)問(wèn)題:
”O(jiān)OP中我們通過(guò)構(gòu)造不同的對(duì)象來(lái)完成不同的功能,最終在這些實(shí)例的共同努力下完成既定的任務(wù)。那么我們以主體或者說(shuō)調(diào)度者的視野來(lái)看,我真的關(guān)心我拿到的這些實(shí)例到底是個(gè)什么嗎戳葵?”
答案顯而易見(jiàn),我并不關(guān)心,我一點(diǎn)都不關(guān)心, 我不關(guān)心你是個(gè)什么,我不關(guān)心你里面裝了什么,我不關(guān)心你是怎么被構(gòu)建出來(lái)的假勿,我僅僅只關(guān)心你是否能正確完成我要求你完成的那幾個(gè)功能(即我只關(guān)心你是否能正確完成你所聲明的那幾個(gè)方法(接口定義)羽戒,更極端點(diǎn)說(shuō)份乒,就算這幾個(gè)方法里,你只要把我們關(guān)心(即調(diào)用)的那個(gè)方法實(shí)現(xiàn)對(duì)腕唧,哪怕其他的方法你全給實(shí)現(xiàn)錯(cuò)了或辖,我也認(rèn)為你合格了,我不關(guān)心你的'品質(zhì)','出生','思想覺(jué)悟'等等其他一切事情枣接。)颂暇。在《七周七語(yǔ)言》這本書(shū)里里有這樣一個(gè)詞:“鴨子類(lèi)型”—— 用蹼走路,會(huì)呱呱叫但惶,它就是鴨子耳鸯。用在這里應(yīng)該非常合適吧湿蛔。
這里舉一個(gè)讓我頓悟的例子,這個(gè)例子來(lái)自于《Mastering Ninject for Dependency Injection》(這書(shū)只有英文版, 當(dāng)初咬牙把英文版的看完了, 緊接著放該電子文件的U盤(pán)壞了, 靠县爬!三年了煌集, 至今記得當(dāng)時(shí)那個(gè)恨啦!)捌省。文中以木匠和手術(shù)的主刀醫(yī)生為例,木匠在干活時(shí)他所使用的工具都需要自己去鹊锬啤纲缓;而主刀醫(yī)生在干活時(shí)工具都是由助手遞過(guò)去的,主刀醫(yī)生根本不需要關(guān)心工具的來(lái)源喊废。他只需要關(guān)注于自己的本質(zhì)工作即可祝高,而木匠除了本質(zhì)工作之外,還得負(fù)責(zé)找出合適的工具來(lái)完成這件事污筷。
那好工闺,既然我這么多不關(guān)心,那么對(duì)象的構(gòu)造工作完全沒(méi)必要放在我這里瓣蛀,我想要的是一個(gè)"容器", 在“真正需要”的時(shí)候從中取出那個(gè)實(shí)現(xiàn)了我想要的功能的那個(gè)對(duì)象陆蟆,僅此而已。另外《Clean Code》里就專(zhuān)門(mén)有一章來(lái)講解我們應(yīng)該將對(duì)象的構(gòu)建和對(duì)象的使用區(qū)分開(kāi)惋增。
所以:
- 想清楚自己真正需要的到底是什么叠殷?
- 相比較應(yīng)該知道什么,知道自己不該知道什么也很重要诈皿。
2. AOP
在討論AOP之前林束,請(qǐng)先看看下面這句“優(yōu)秀框架的基本素質(zhì)之一就是在關(guān)鍵的過(guò)程中設(shè)置攔截性接口,越通用的框架就越不應(yīng)該對(duì)用戶的行為進(jìn)行任何假設(shè)性的約束稽亏,包括框架自身的行為都最好是以擴(kuò)展的方式并入”壶冒。
如果你很好奇我為什么突然說(shuō)這句?那么接下來(lái)就是重點(diǎn):其實(shí)這段話里的關(guān)鍵字就是那個(gè)“攔截性接口”截歉;現(xiàn)在讓我們回想下AOP的使用場(chǎng)景胖腾,是否可以概括為這樣一句話:我希望在xx方法執(zhí)行的前后進(jìn)行某些操作,甚至可以根據(jù)操作的結(jié)果來(lái)決定是否執(zhí)行這個(gè)方法的實(shí)際邏輯怎披。聯(lián)系前后兩個(gè)胸嘁,是不是非常非常相似!具體的代碼我就不重復(fù)凉逛,網(wǎng)上一堆性宏。這里我就貼一下Java中的兩種實(shí)現(xiàn)方式吧:
a. Java實(shí)現(xiàn)AOP之動(dòng)態(tài)代理
動(dòng)態(tài)代理有以下特點(diǎn):
- 代理類(lèi)所在包:
java.lang.reflect.Proxy
- 代理對(duì)象,不需要實(shí)現(xiàn)接口。
- 代理對(duì)象的生成,是利用JDK的API,動(dòng)態(tài)的在內(nèi)存中構(gòu)建代理對(duì)象(需要我們指定創(chuàng)建代理對(duì)象/目標(biāo)對(duì)象實(shí)現(xiàn)的接口的類(lèi)型)
- 動(dòng)態(tài)代理也叫做JDK代理状飞,接口代理毫胜。
b. Java實(shí)現(xiàn)AOP之Cglib子類(lèi)代理
Cglib子類(lèi)代理實(shí)現(xiàn)方法:
1.需要引入cglib的jar文件书斜,但是Spring的核心包中已經(jīng)包括了Cglib功能,所以直接引入spring-core-3.x.x.jar
即可酵使。
2.引入功能包后,就可以在內(nèi)存中動(dòng)態(tài)構(gòu)建子類(lèi)荐吉。
3.代理的類(lèi)不能為final,否則報(bào)錯(cuò)口渔。
4.目標(biāo)對(duì)象的方法如果為final/static样屠,那么就不會(huì)被攔截,即不會(huì)執(zhí)行目標(biāo)對(duì)象額外的業(yè)務(wù)方法。
關(guān)于AOP的好處我就不多說(shuō)了缺脉。下面是開(kāi)濤大神的鏈接地址痪欲,代碼什么都有。
3. 聯(lián)系
IOC和AOP相輔相成攻礼;因?yàn)槟悴魂P(guān)心拿到的是什么业踢,所以我可以在你拿到這個(gè)實(shí)現(xiàn)所需功能的對(duì)象之前,我可以對(duì)它進(jìn)行修改礁扮,附加上一些東西知举,甚至整個(gè)將它們替換掉,而這些附加的功能最終會(huì)在特定時(shí)刻發(fā)生效果太伊,而這些特定時(shí)刻就是我們?cè)谠O(shè)置AOP時(shí)的約束雇锡。
具體實(shí)例就是Spring容器了,其思想和sql類(lèi)似——你告訴我對(duì)象有些啥倦畅,以及它們之間的關(guān)系遮糖,剩下的工作就交給我了。也是因?yàn)閷?shí)際的構(gòu)建過(guò)程由Spring負(fù)責(zé)叠赐,而你又不關(guān)心實(shí)際的對(duì)象(你關(guān)心的是功能是否如期實(shí)現(xiàn))欲账,那么AOP就順理成章了。
再做一點(diǎn)引申閱讀吧芭概。這是不是有點(diǎn)像JVM所處理的class文件赛不,JVM只要求你傳遞的文件符合既定要求,至于這個(gè)文件是何處而來(lái)罢洲,傳遞給JVM之前是否有過(guò)二次轉(zhuǎn)換踢故,JVM其實(shí)一點(diǎn)都不關(guān)心,這就給了各種編譯器以無(wú)限大的自由度去進(jìn)行各種自定制惹苗,關(guān)于這一點(diǎn)大家可以閱讀《深入理解Java虛擬機(jī)》殿较,我這里就不越皰代俎了。
4. Links
- 《SICP》—— 會(huì)當(dāng)凌絕頂一覽眾山小桩蓉,不多解釋了淋纲!
- 《Clean Code》—— 此書(shū)之后,再無(wú)代碼規(guī)范院究。
- 《優(yōu)秀框架的基本素質(zhì)》—— 這是一篇博客洽瞬;作者是阿里的梁飛本涕。
- 我對(duì)AOP的理解 -- 開(kāi)濤大神的,里面有示例代碼等伙窃。我就不再自己重復(fù)一遍了菩颖。