AOP的理解以及示例

關(guān)于Spring AOP的理解

AOP為Aspect Oriented Programming的縮寫(xiě) :面向切面編程锋边, AOP是OOP的延續(xù) AOP并不是一種技術(shù),只是一種思想险胰,即面向切面編程的思想

在開(kāi)發(fā)中日志的使用時(shí)很頻繁的捌臊,下面就來(lái)用AOP來(lái)解決一下開(kāi)發(fā)中的日志輸出的問(wèn)題

@Service
public class TestService {

    public int sum(int a ,int b ){
        System.out.println("參數(shù)為:"+a+"+"+b);
        int sum = a+b;
        System.out.println("結(jié)果為:"+sum);
        return sum;
    }
}
@Autowired
private TestService testService;

@Test
void contextLoads() {
    testService.sum(1,2);
}
參數(shù)為:1+2
結(jié)果為:3

在不使用aop的情況下豁鲤,我們打印日志要這樣寫(xiě)或链,這樣寫(xiě)的話就是業(yè)務(wù)代碼跟日志輸出都寫(xiě)在了一起惫恼,使得代碼冗余,而且在后面假如說(shuō)澳盐,不需要將參數(shù)輸出到日志中了祈纯,這樣需要一個(gè)類(lèi)一個(gè)類(lèi)的修改代碼,工作量時(shí)很大的

AOP就很方便簡(jiǎn)單的解決了這個(gè)問(wèn)題

AOP的理解

image-20200815173638193.png

這是之前的日志輸出方法

image-20200815173809830.png

這個(gè)時(shí)使用AOP的日志輸出方法

其實(shí)AOP叼耙,面向切面很好理解腕窥,就是在一個(gè)類(lèi)上橫切一刀,將我們需要的代碼切入筛婉,并且不影響之前代碼的執(zhí)行簇爆,實(shí)現(xiàn)了解耦

image-20200815181439994.png

AOP的優(yōu)點(diǎn)

1、面向切面編程使得每個(gè)關(guān)注點(diǎn)都集中于一個(gè)地方而不是分散在多處代碼中爽撒,便于后期的統(tǒng)一維護(hù)管理冕碟。

2、服務(wù)模塊更簡(jiǎn)潔匆浙,它們只包含主要關(guān)注點(diǎn),而次要關(guān)注點(diǎn)的代碼被轉(zhuǎn)移到切面中了厕妖。

3首尼、對(duì)原方法進(jìn)行方法增強(qiáng),且不影響原方法的正常使用。

4软能、使用簡(jiǎn)單可插拔的配置迎捺,在實(shí)際邏輯執(zhí)行之前、之后或周?chē)鷦?dòng)態(tài)添加橫切關(guān)注點(diǎn)查排。

AOP的術(shù)語(yǔ)

名稱(chēng) 描述
切面(Aspect) 切面是通知和切點(diǎn)的結(jié)合
通知(Advice) 通知定義了切面是什么以及何時(shí)使用凳枝。除了描述切面要完成的工作,通知還解決了何時(shí)執(zhí)行這個(gè)工作的問(wèn)題
切點(diǎn)(Pointcut) 切點(diǎn)定義了在何處工作跋核,也就是真正被切入的地方岖瑰,也就是在哪個(gè)方法應(yīng)用通知
連接點(diǎn)(Join point) 連接點(diǎn)是在應(yīng)用執(zhí)行過(guò)程中能夠插入切面的一個(gè)點(diǎn)
引入(Introduction) 引入讓一個(gè)切面可以聲明被通知的對(duì)象實(shí)現(xiàn)了任何他們沒(méi)有真正實(shí)現(xiàn)的額外接口,而且為這些對(duì)象提供接口的實(shí)現(xiàn)
織入(Weaving) 織入是把切面應(yīng)用到目標(biāo)對(duì)象并創(chuàng)建新的代理對(duì)象的過(guò)程

其中在Spring中有5中通知類(lèi)型

名稱(chēng) 描述
前置通知(Before) 在目標(biāo)方法被調(diào)用之前調(diào)用
后置通知(After) 在目標(biāo)方法完成之后調(diào)用
返回通知(After-returning) 在目標(biāo)方法成功執(zhí)行之后調(diào)用
異常通知(After-throwing) 在目標(biāo)方法拋出異常后調(diào)用
環(huán)繞通知(Around) 通知包裹了被通知的方法砂代,可同時(shí)定義前置通知和后置通知

SpringBoot 實(shí)現(xiàn)AOP

  1. 新建一個(gè)SpringBoot項(xiàng)目

  2. 導(dǎo)入依賴(lài)

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
    </dependency>
    
  3. AOP的實(shí)現(xiàn)需要進(jìn)行配置蹋订,在Spring 中使用的時(shí)xm的方式進(jìn)行配置,但是在SpringBoot中取消了xml刻伊,改為使用了配置類(lèi)進(jìn)行配置

    package com.mango.Aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    /**
     * @Author:  
     * @Date:     
     * @Component 被Spring管理
     * @Aspect 聲明他是一個(gè)aop的類(lèi)
     */
    @Component
    @Aspect
    public class TestAspect {
    
        /**
         *  @Pointcut("execution(* com.mango.service.*.*(..))")
         *  execution 括號(hào)中的是一個(gè)表達(dá)式露戒,表面在com.mango.service 這個(gè)包下的所有類(lèi)所有方法所有返回值,所有參數(shù)
         *  申明切入點(diǎn)
         *  execution 關(guān)鍵字
         *  *           com.mango.service. *.    *          (..)  )
         *  所有的返回值  包名                         所有類(lèi) 所有方法   所有的參數(shù)
         */
        @Pointcut("execution(* com.mango.service.*.*(..))")
        public void pointcut(){}
    
        /**
         * @Before("pointcut()")  前置通知捶箱,在切入點(diǎn)之前
         * @param joinPoint  可以通過(guò)他來(lái)獲取方法以及參數(shù)
         */
        @Before("pointcut()")
        public void before(JoinPoint joinPoint){
            Object [] args = joinPoint.getArgs();
            for (Object arg : args) {
                System.out.println("參數(shù)為:"+arg);
    
            }
        }
    
        /**
         * @param joinPoint
         * @param returnValue
         * @AfterReturning(value = "pointcut()",returning = "returnValue")
         * returning 獲取返回值
         */
        @AfterReturning(value = "pointcut()",returning = "returnValue")
        public void returning(JoinPoint joinPoint,Object returnValue){
            System.out.println("結(jié)果為:"+returnValue);
        }
    }
    
@Service
public class TestService {

    public int sum(int a ,int b ){

        int sum = a+b;

        return sum;
    }
}
@SpringBootTest
class SpringbootAopApplicationTests {
    @Autowired
    private TestService testService;

    @Test
    void contextLoads() {
        testService.sum(1,2);
    }

}
參數(shù)為:1
參數(shù)為:2
結(jié)果為:3

其他的After之類(lèi)的就不再舉例了智什,用法都是一樣的

這樣就是實(shí)現(xiàn)了AOP,是不是很簡(jiǎn)單丁屎,其實(shí)AOP的使用時(shí)很簡(jiǎn)單的荠锭,重要的是理解AOP的這種思想

AOP的運(yùn)用的技術(shù)

SpringAOP使用了兩種代理機(jī)制,一種是基于JDK的動(dòng)態(tài)代理悦屏,另一種是基于CGLib的動(dòng)態(tài)代理节沦,之所以需要兩種代理機(jī)制,很大程度上是因?yàn)镴DK本身只提供基于接口的代理础爬,不支持類(lèi)的代理甫贯。

切面植入的方法:

編譯期織

類(lèi)裝載期織入

動(dòng)態(tài)代理織入 在運(yùn)行期為目標(biāo)類(lèi)添加增強(qiáng)生成子類(lèi)的方式,Spring AOP采用動(dòng)態(tài)代理織入切面

AOP 有兩種主要的框架看蚜,SpringAOP和AspectJ

在一般情況下使用SpringAOP就可以解決我們的問(wèn)題叫搁,如果無(wú)法解決,Spring支持對(duì)AspectJ 的集成供炎,可以使用AspectJ解決

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末渴逻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子音诫,更是在濱河造成了極大的恐慌惨奕,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竭钝,死亡現(xiàn)場(chǎng)離奇詭異梨撞,居然都是意外死亡雹洗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)卧波,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)时肿,“玉大人,你說(shuō)我怎么就攤上這事港粱◇Τ桑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵查坪,是天一觀的道長(zhǎng)寸宏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)咪惠,這世上最難降的妖魔是什么击吱? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮遥昧,結(jié)果婚禮上覆醇,老公的妹妹穿的比我還像新娘。我一直安慰自己炭臭,他們只是感情好永脓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著鞋仍,像睡著了一般常摧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上威创,一...
    開(kāi)封第一講書(shū)人閱讀 51,215評(píng)論 1 299
  • 那天落午,我揣著相機(jī)與錄音,去河邊找鬼肚豺。 笑死溃斋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吸申。 我是一名探鬼主播梗劫,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼截碴!你這毒婦竟也來(lái)了梳侨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤日丹,失蹤者是張志新(化名)和其女友劉穎走哺,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體哲虾,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丙躏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年齐帚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彼哼。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖湘今,靈堂內(nèi)的尸體忽然破棺而出敢朱,到底是詐尸還是另有隱情,我是刑警寧澤摩瞎,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布拴签,位于F島的核電站,受9級(jí)特大地震影響旗们,放射性物質(zhì)發(fā)生泄漏蚓哩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一上渴、第九天 我趴在偏房一處隱蔽的房頂上張望岸梨。 院中可真熱鬧,春花似錦稠氮、人聲如沸曹阔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赃份。三九已至,卻和暖如春奢米,著一層夾襖步出監(jiān)牢的瞬間抓韩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工鬓长, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谒拴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓痢士,卻偏偏與公主長(zhǎng)得像彪薛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子怠蹂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354