測試同學(xué)上手Spring 之AOP最易懂的解析

前面連續(xù)介紹了幾篇上手Spring的基礎(chǔ)文章

測試同學(xué)從0到1上手Spring

測試同學(xué)上手Spring 之IoC深入解析

測試同學(xué)上手Spring 之DI深入解析

AOP解析

今天來介紹Spring的另一個核心技術(shù)點AOP,AOP的概念不好理解卿啡,希望大家仔細閱讀文章并按照文章中的代碼進行練習(xí)岛杀,屆時一定會有很大的收獲植榕!

AOP (Aspect OrientProgramming),直譯過來就是 面向切面編程沧踏。AOP 是一種編程思想步悠,是面向?qū)ο缶幊蹋∣OP)的一種補充。面向?qū)ο缶幊虒⒊绦虺橄蟪筛鱾€層次的對象常空,而面向切面編程是將程序抽象成各個切面沽一。從《Spring實戰(zhàn)(第4版)》圖書中扒了一張圖:

從該圖可以很形象地看出,所謂切面漓糙,相當于應(yīng)用對象間的橫切點铣缠,我們可以將其單獨抽象為單獨的模塊。

Spring提供了面向切面編程的豐富支持昆禽,是通過動態(tài)代理實現(xiàn)的蝗蛙。允許通過分離應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)級服務(wù)(例如:審計(auditing)和事務(wù)(transaction)管理)進行內(nèi)聚性的開發(fā)。應(yīng)用對象只實現(xiàn)它們應(yīng)該做的——完成業(yè)務(wù)邏輯——僅此而已醉鳖。它們并不負責(zé)(甚至是意識到)其它系統(tǒng)級別的關(guān)注點捡硅,例如:日志或事務(wù)支持。

AOP 要達到的效果是盗棵,保證開發(fā)者在不修改源代碼的前提下壮韭,去為系統(tǒng)中的業(yè)務(wù)組件添加某種通用功能。

AOP基本運行流程如下圖所示:

AOP 領(lǐng)域中的特性術(shù)語:

橫切關(guān)注點:跨越應(yīng)用程序多個模塊的方法或功能纹因。即是與我們業(yè)務(wù)邏輯無關(guān)的喷屋,但是我們需要關(guān)注的部分,就是橫切關(guān)注點瞭恰。如日志 , 安全 , 緩存 , 事務(wù)等等....

切面(ASPECT):橫切關(guān)注點被模塊化的特殊對象屯曹。即,它是一個類惊畏。

通知(Advice):AOP 框架中的增強處理恶耽。通知描述了切面何時執(zhí)行以及如何執(zhí)行增強處理。它是類中的一個方法颜启。

目標(Target):被通知對象偷俭。

代理(Proxy):向目標對象應(yīng)用通知之后創(chuàng)建的對象。

連接點(JointPoint):表示應(yīng)用執(zhí)行過程中能夠插入切面的一個點农曲,這個點可以是方法的調(diào)用社搅、異常的拋出。在 Spring AOP 中乳规,連接點總是方法的調(diào)用形葬。

切入點(PointCut):可以插入增強處理的連接點。

引入(Introduction):引入允許我們向現(xiàn)有的類添加新的方法或者屬性暮的。

織入(Weaving): 將增強處理添加到目標對象中笙以,并創(chuàng)建一個被增強的對象,這個過程就是織入冻辩。

Advice通知

通知(Advice)是切面的一種實現(xiàn)猖腕,可以完成簡單織入功能(織入功能就是在這里完成的)拆祈。Spring AOP 中有 5 中通知類型,分別如下:

各個通知的執(zhí)行順序如下圖所示:

實例編碼

需求:在類中添加日志功能倘感,如下圖:

實現(xiàn)方法1:在各個類中添加方法logMsg()放坏。如果類數(shù)量少,問題不大老玛,如果有幾百個類需要處理淤年,那么工作量就很大了。

實現(xiàn)方法2:通過aop來實現(xiàn)

首先蜡豹,mvn中添加配置

實例如下:

創(chuàng)建接口

public interface UserService {

??? ?? public void add();

??? ?? public void delete();

??? ?? public void update();

??? ?? public void search();

??? }

創(chuàng)建切入點類

public class UserServiceImpl implements UserService {

??? ? public void add() {

??? ??????System.out.println("增加用戶");

??? ? }

??? ?? public void delete() {

??? ??????System.out.println("刪除用戶");

??? ? }

??? ?? public void update() {

??? ??????System.out.println("更新用戶");

??? ? }

??? ?? public void search() {

??? ??????System.out.println("查詢用戶");

??? ? }

創(chuàng)建類麸粮,實現(xiàn)@Before通知

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class BeforeLog implements MethodBeforeAdvice {

??? ?? //method : 要執(zhí)行的目標對象的方法

??? ?? //objects : 被調(diào)用的方法的參數(shù)

??? ?? //Object : 目標對象

??? ?? public void before(Method method, Object[] objects, Object o) throws Throwable {

??? ??????System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被執(zhí)行了");

??? ? }

??? }

創(chuàng)建類,實現(xiàn)@After通知

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class AfterLog implements AfterReturningAdvice {

??? ?? //returnValue 返回值

??? ?? //method被調(diào)用的方法

??? ?? //args被調(diào)用的方法的對象的參數(shù)

??? ?? //target 被調(diào)用的目標對象

??? ?? public void afterReturning(Object returnValue,

Method method, Object[] args, Object target) throws Throwable {

??? ??????System.out.println("執(zhí)行了" + target.getClass().getName()

??? ??????+"的"+method.getName()+"方法,"

??? ??????+"返回值:"+returnValue);

??? ? }

??? }

編輯xml文件

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

??? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

??? xmlns:context="http://www.springframework.org/schema/context"

??? xmlns:aop="http://www.springframework.org/schema/aop"

??? xmlns:p="http://www.springframework.org/schema/p"

??? xmlns:c="http://www.springframework.org/schema/c"

??? xsi:schemaLocation="http://www.springframework.org/schema/beans

???????https://www.springframework.org/schema/beans/spring-beans.xsd

???????http://www.springframework.org/schema/context

???????https://www.springframework.org/schema/context/spring-context.xsd

???????http://www.springframework.org/schema/aop

??????? http://www.springframework.org/schema/aop/spring-aop.xsd">

??? <context:annotation-config/>

?<!--注冊bean-->

?? <beanid="userService"class="com.my.demo.aop.UserServiceImpl"/>

?? <beanid="beforelog"class="com.my.demo.aop.BeforeLog"/>

?? <beanid="afterLog"class="com.my.demo.aop.AfterLog"/>

?? <aop:config>

?????? <!--切入點 expression:表達式匹配要執(zhí)行的方法-->

?????? <aop:pointcutid="pointcut"expression="execution(*

com.my.demo.aop.UserServiceImpl.*(..))"/>

?????? <!--執(zhí)行環(huán)繞; advice-ref執(zhí)行方法.pointcut-ref切入點-->

?????? <aop:advisoradvice-ref="beforelog"pointcut-ref="pointcut"/>

?????? <aop:advisoradvice-ref="afterLog"pointcut-ref="pointcut"/>

?? </aop:config>

</beans>

測試類如下:

??? ?public static void main(String[] args) {

??????? ?ApplicationContextcontext = new ClassPathXmlApplicationContext("bean3.xml");

??? ??????UserServiceuserService = (UserService) context.getBean("userService");

??? ??????userService.search();

??? }

執(zhí)行測試代碼镜廉,結(jié)果如下


com.my.demo.aop.UserServiceImpl的search方法被執(zhí)行了?//before方法執(zhí)行

查詢用戶?//UserServiceImpl中的search方法

執(zhí)行執(zhí)行了com.my.demo.aop.UserServiceImpl的search方法,返回值:null//after方法執(zhí)行


可以發(fā)現(xiàn)由于實現(xiàn)了@Before通知@After通知稚晚,我們在調(diào)用方法前后辙芍,就分別自動對before 和afterReturning完成了調(diào)用抚垄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末戒良,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子视乐,更是在濱河造成了極大的恐慌洛搀,老刑警劉巖敢茁,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佑淀,死亡現(xiàn)場離奇詭異,居然都是意外死亡彰檬,警方通過查閱死者的電腦和手機伸刃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逢倍,“玉大人捧颅,你說我怎么就攤上這事〗系瘢” “怎么了碉哑?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長亮蒋。 經(jīng)常有香客問我扣典,道長,這世上最難降的妖魔是什么慎玖? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任贮尖,我火速辦了婚禮,結(jié)果婚禮上趁怔,老公的妹妹穿的比我還像新娘湿硝。我一直安慰自己薪前,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布关斜。 她就那樣靜靜地躺著示括,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痢畜。 梳的紋絲不亂的頭發(fā)上例诀,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音裁着,去河邊找鬼繁涂。 笑死,一個胖子當著我的面吹牛二驰,可吹牛的內(nèi)容都是我干的扔罪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼桶雀,長吁一口氣:“原來是場噩夢啊……” “哼矿酵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起矗积,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤全肮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后棘捣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辜腺,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年乍恐,在試婚紗的時候發(fā)現(xiàn)自己被綠了评疗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡茵烈,死狀恐怖百匆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情呜投,我是刑警寧澤加匈,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站仑荐,受9級特大地震影響雕拼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜释漆,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一悲没、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦示姿、人聲如沸甜橱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岂傲。三九已至,卻和暖如春子檀,著一層夾襖步出監(jiān)牢的瞬間镊掖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工褂痰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亩进,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓缩歪,卻偏偏與公主長得像归薛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子匪蝙,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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