Spring基礎(chǔ)-AOP面向切面編程

什么是AOP及其作用

1攒暇、AOP被稱之為面向切面(方面)編程(Aspect Oriented Programming)簡寫
2铺纽、AOP可以對業(yè)務(wù)邏輯各個方面進行隔離趟咆,從而降低代碼的耦合性呵扛,提高代碼的可復(fù)用性
通俗講就是在不通過修改源碼的情況下實現(xiàn)主干功功能上增加新的功能

AOP中常用術(shù)語

1电湘、連接點:類中需要被增強的方法都稱之為連接點
2隔节、切入點:實際被增強的方法被稱之切入點
3、通知(增強):實際增強的邏輯被稱之為通知
4胡桨、切面:切面是一個過程官帘,將通知應(yīng)用到切入點的過程被稱之為切面

通知的類型

1瞬雹、前置通知:切入點之前執(zhí)行的邏輯
2昧谊、后置通知:切入點之后執(zhí)行的邏輯
3、環(huán)繞通知:切入點前后都執(zhí)行邏輯
4酗捌、異常通知:當切入點發(fā)生異常后的邏輯
5呢诬、返回通知:當返回結(jié)果是執(zhí)行的邏輯

上述通知代碼

1、pom.xml

<dependencies>
    <!-- junit測試包 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- spring-context 包含Spring-->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.6.RELEASE</version>
    </dependency>

    <!-- aspectj -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.8.13</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
      <scope>runtime</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/cglib/cglib -->
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.3.0</version>
    </dependency>
    <!-- aspectj -->
  </dependencies>

2胖缤、BookDao需要被增強的類

package work.chenc.spring.dao;

import org.springframework.stereotype.Component;

// 需要增強類
@Component
public class BookDao {

    // 可以被增強的方法-連接點
    public void insert() {
        int A = 10 / 0;
        System.out.println("執(zhí)行了insert().........:" + A);
    }

    // 需要被增強的方法-切入點
    public void add() {
        System.out.println("執(zhí)行了add().........");
    }

}

3尚镰、BookProxy增強類—在什么位置對BookDao類中的方法進行增強邏輯

package work.chenc.spring.proxy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

// 增強類
@Component
@Aspect
public class BookProxy {
    // 相同切入點的抽取
    @Pointcut(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void pointcutDemo() { }

    // 前置通知
   //   @Before(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    // 自定義公共切入點的使用
    @Before(value = "pointcutDemo()")
    public void before() {
        System.out.println("前置通知——執(zhí)行了before()方法");
    }

    // 后置通知 - 在方法執(zhí)行之后執(zhí)行
    @After(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void after() {
        System.out.println("后置通知——執(zhí)行了after()方法");
    }

    // 返回通知-在方法返回后執(zhí)行
    @AfterReturning(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void afterReturning() {
        System.out.println("后置通知——執(zhí)行了afterReturning()方法");
    }

    // 環(huán)繞通知
    @Around(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("環(huán)繞通知之前-----------");
        proceedingJoinPoint.proceed();
        System.out.println("環(huán)繞通知之前-----------");
    }

    // 異常通知
    @AfterThrowing(value = "execution(* work.chenc.spring.dao.BookDao.insert(..))")
  public void afterThrowing() {
        System.out.println("異常通知........");
    }
}

4、bean.xml—開啟注解掃描 開啟Aspectj生成代理對象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://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 https://www.springframework.org/schema/aop/spring-aop.xsd">
  
  <!-- 
    這里新增了一個aop的名名稱空間
    xmlns:aop="http://www.springframework.org/schema/aop"
   -->
  
  <!-- 開啟注解掃描 -->
  <context:component-scan base-package="work.chenc.spring.*"></context:component-scan>

  <!--
    開啟Aspect注解生成代理對象
    到開啟注解掃描的類里面尋找有@Aspect注解的類哪廓,并聲稱對應(yīng)的代理對象
  -->
  <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

5狗唉、測試類

@Test
public void aspectTest() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:bean.xml");
    BookDao bookDao = applicationContext.getBean("bookDao", BookDao.class);
    // 測試非異常通知
        // bookDao.add();
    // 測試異常通知
    bookDao.insert();
}  

AOP部分解釋說明

1)什么是AspectJ
AspectJ不是Spring的組成部分,是獨立的AOP框架涡真,一般把AspectJ和Spring框架一起使用分俯,進行AOP操作

2)切入點表達式
execution([權(quán)限修飾符][返回類型][類的全路徑]方法名稱)
execution(* work.chenc.spring.dao.BookDao.add(..))
[權(quán)限修飾符]:public default protected private *表示所有
[返回類型]:Java中的類如String int 等自定義類型,空格表示void

3)相同切入點的抽取前置通知中有使用

@Pointcut(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
public void pointcutDemo() {}

AOP存在多個增強類對同一個方法增強時哆料,設(shè)置增強類的優(yōu)先級

目標

存在BookProxy和BookOtherProxy兩個增強類對通一個方法進行增強缸剪,BookOtherProxy中的增強方法先執(zhí)行
代碼如下
1)新增一個增強類BookOtherProxy

package work.chenc.spring.proxy;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(1)
public class BookOtherProxy {

    @Pointcut(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void pointcut() {

    }

    @Before(value = "pointcut()")
    public void before() {
        System.out.println("BookOtherProxy........");
    }

}

2)在原有的BookProxy中新增一個注解@Order(2)

package work.chenc.spring.proxy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

// 增強類
@Component
@Aspect
@Order(2)
public class BookProxy {

    // 相同切入點的抽取
    @Pointcut(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void pointcutDemo() {}

  // 前置通知
//  @Before(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    // 自定義公共切入點的使用
    @Before(value = "pointcutDemo()")
    public void before() {
        System.out.println("前置通知——執(zhí)行了before()方法");
    }

    // 后置通知 - 在方法執(zhí)行之后執(zhí)行
    @After(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void after() {
        System.out.println("后置通知——執(zhí)行了after()方法");
    }

    // 返回通知-在方法返回后執(zhí)行
    @AfterReturning(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void afterReturning() {
        System.out.println("后置通知——執(zhí)行了afterReturning()方法");
    }

    // 環(huán)繞通知
    @Around(value = "execution(* work.chenc.spring.dao.BookDao.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("環(huán)繞通知之前-----------");
        proceedingJoinPoint.proceed();
        System.out.println("環(huán)繞通知之前-----------");
    }

    // 異常通知
    @AfterThrowing(value = "execution(* work.chenc.spring.dao.BookDao.insert(..))")
    public void afterThrowing() {
        System.out.println("異常通知........");
    }
}

@Order()解釋
Order這里的注解是對增強方法進行優(yōu)先級的區(qū)分括號中的填入數(shù)字,從0開始东亦,數(shù)字越大杏节,優(yōu)先級越低
通過上述的代碼先執(zhí)行的是BookOtherProxy中的前置通知before(),然后再執(zhí)行BookProxy中的前置通知

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奋渔,隨后出現(xiàn)的幾起案子镊逝,更是在濱河造成了極大的恐慌,老刑警劉巖嫉鲸,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹋半,死亡現(xiàn)場離奇詭異,居然都是意外死亡充坑,警方通過查閱死者的電腦和手機减江,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捻爷,“玉大人辈灼,你說我怎么就攤上這事∫查” “怎么了巡莹?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長甜紫。 經(jīng)常有香客問我降宅,道長,這世上最難降的妖魔是什么囚霸? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任腰根,我火速辦了婚禮,結(jié)果婚禮上拓型,老公的妹妹穿的比我還像新娘额嘿。我一直安慰自己,他們只是感情好劣挫,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布册养。 她就那樣靜靜地躺著,像睡著了一般压固。 火紅的嫁衣襯著肌膚如雪球拦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天帐我,我揣著相機與錄音坎炼,去河邊找鬼。 笑死焚刚,一個胖子當著我的面吹牛点弯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播矿咕,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼抢肛,長吁一口氣:“原來是場噩夢啊……” “哼狼钮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捡絮,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤熬芜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后福稳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涎拉,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年的圆,在試婚紗的時候發(fā)現(xiàn)自己被綠了鼓拧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡越妈,死狀恐怖季俩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情梅掠,我是刑警寧澤酌住,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站阎抒,受9級特大地震影響酪我,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜且叁,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一都哭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谴古,春花似錦质涛、人聲如沸稠歉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怒炸。三九已至带饱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阅羹,已是汗流浹背勺疼。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捏鱼,地道東北人执庐。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像导梆,于是被迫代替她去往敵國和親轨淌。 傳聞我的和親對象是個殘疾皇子迂烁,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

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