AOP設(shè)計(jì)基本原理
什么是AOP(即面向切面編程)欲账?
通常面向?qū)ο蟮某绦颍a都是按照時(shí)間序列縱向展開的,而他們都有一個(gè)共性:即都是以方法調(diào)用作為基本執(zhí)行單位展開的瀑焦。將方法調(diào)用當(dāng)做一個(gè)連接點(diǎn)荆针,那么由連接點(diǎn)串起來的程序執(zhí)行流就是整個(gè)程序的執(zhí)行過程敞嗡。
AOP則是從另外一個(gè)角度來考慮整個(gè)程序的,AOP將每一個(gè)方法調(diào)用航背,即連接點(diǎn)作為編程的入口喉悴,針對(duì)方法調(diào)用進(jìn)行編程。從執(zhí)行的邏輯上來看玖媚,相當(dāng)于在之前縱向的按照時(shí)間軸執(zhí)行的程序橫向切入箕肃。相當(dāng)于將之前的程序橫向切割成若干的面,即Aspect每個(gè)面被稱為切面今魔。
所以勺像,根據(jù)我的理解,AOP本質(zhì)上是針對(duì)方法調(diào)用的編程思路错森。
既然AOP是針對(duì)切面進(jìn)行的編程的吟宦,那么,你需要選擇哪些切面(即 連接點(diǎn)Joint Point)作為你的編程對(duì)象呢涩维?
因?yàn)榍忻姹举|(zhì)上是每一個(gè)方法調(diào)用督函,選擇切面的過程實(shí)際上就是選擇方法的過程。那么激挪,被選擇的切面(Aspect)在AOP術(shù)語里被稱為切入點(diǎn)(Point Cut).? 切入點(diǎn)實(shí)際上也是從所有的連接點(diǎn)(Join point)挑選自己感興趣的連接點(diǎn)的過程辰狡。
代理模式的引入:
加入了代理模式的Java程序執(zhí)行流,使得所有的方法調(diào)用都經(jīng)過了代理對(duì)象垄分。對(duì)于Spring AOP框架而言宛篇,它負(fù)責(zé)控制著真?zhèn)€容器內(nèi)部的代理對(duì)象。當(dāng)我們調(diào)用了某一個(gè)實(shí)例對(duì)象的任何一個(gè)非final的public方法時(shí)薄湿,整個(gè)Spring框架都會(huì)知曉叫倍。
此時(shí)的SpringAOP框架在某種程度上扮演著一個(gè)上帝的角色:它知道你在這個(gè)框架內(nèi)所做的任何操作,你對(duì)每一個(gè)實(shí)例對(duì)象的非final的public方法調(diào)用都可以被框架察覺到豺瘤!
既然Spring代理層可以察覺到你所做的每一次對(duì)實(shí)例對(duì)象的方法調(diào)用吆倦,那么,Spring就有機(jī)會(huì)在這個(gè)代理的過程中插入Spring的自己的業(yè)務(wù)代碼坐求。
Spring AOP的工作原理
為了降低我們對(duì)Spring的AOP的理解難度蚕泽,我在這里將代理角色的職能進(jìn)行了簡化,方便大家理解。(注意:真實(shí)的Spring AOP的proxy角色扮演的只能比這復(fù)雜的多须妻,這里只是簡化仔蝌,方便大家理解,請(qǐng)不要先入為主)代理模式的代理角色最起碼要考慮三個(gè)階段:
1.在調(diào)用真正對(duì)象的方法之前荒吏,應(yīng)該需要做什么敛惊?
2.在調(diào)用真正對(duì)象的方法過程中,如果拋出了異常绰更,需要做什么瞧挤?
3.在調(diào)用真正對(duì)象的方法后,返回了結(jié)果了儡湾,需要做什么皿伺?
AOP對(duì)這個(gè)方法調(diào)用的編程,就是針對(duì)這三個(gè)階段插入自己的業(yè)務(wù)代碼盒粮。
現(xiàn)在我們假設(shè)當(dāng)前RealSubject這個(gè)角色的類是org.luanlouis.springlearning.aop.FooService,當(dāng)前這個(gè)連接點(diǎn)對(duì)應(yīng)的方法簽名是:public void foo()奠滑。那么上述的代理對(duì)象的三個(gè)階段將會(huì)有以下的處理邏輯:
1.在調(diào)用真正對(duì)象的方法之前丹皱,
proxy會(huì)告訴Spring AOP:? "我將要調(diào)用類org.luanlouis.springlearning.aop.FooService的public void foo(),在調(diào)用之前宋税,你有什么處理建議嗎摊崭?";
Spring AOP這時(shí)根據(jù)proxy提供的類名和方法簽名,然后拿這些信息嘗試匹配是否在其感興趣的切入點(diǎn)內(nèi),如果在感興趣的切入點(diǎn)內(nèi)杰赛,Spring AOP會(huì)返回MethodBeforeAdvice處理建議呢簸,告訴proxy應(yīng)該執(zhí)行的操作;
2.在調(diào)用真正對(duì)象的方法過程中乏屯,如果拋出了異常根时,需要做什么?
proxy告訴Spring AOP: “我調(diào)用類org.luanlouis.springlearning.aop.FooService的public void foo()過程中拋出了異常辰晕,你有什么處理建議蛤迎?”
Spring AOP根據(jù)proxy提供的類型和方法簽名,確定了在其感興趣的切入點(diǎn)內(nèi)含友,則返回相應(yīng)的處理建議ThrowsAdvice替裆,告訴proxy這個(gè)時(shí)期應(yīng)該采取的操作。
3.在調(diào)用真正對(duì)象的方法后窘问,返回了結(jié)果了辆童,需要做什么?
proxy告訴Spring AOP:"我調(diào)用類org.luanlouis.springlearning.aop.FooService的public void foo()結(jié)束了惠赫,并返回了結(jié)果你現(xiàn)在有什么處理建議把鉴?";
Spring AOP根據(jù)proxy提供的類型名和方法簽名儿咱,確定了在其感興趣的切入點(diǎn)內(nèi)纸镊,則返回AfterReturingAdivce處理建議倍阐,proxy得到這個(gè)處理建議,然后執(zhí)行建議逗威;