你知道面試必問的AOP嗎?通過Spring又如何實現(xiàn)呢?

Aspect Oriented Programing 面向切面編程,相比較 oop 面向?qū)ο缶幊虂碚f,Aop 關(guān)注的不再是程序代碼中某個類,某些方法,而 aop 考慮的更多的是一種面到面的切入,即層與層之間的一種切入,所以稱之為切面。聯(lián)想大家吃的漢堡(中間夾肉)。那么 aop 是怎么做到攔截整個面的功能呢?考慮學(xué)到的 servlet urlpattern /* 的配置,實際上也是 aop 的實現(xiàn) 。

Spring Aop 實現(xiàn)的方式

注解 方式

XML 方式

案例實操

注解方式

jar 包坐標引入

<dependency>

? <groupId>org.aspectj</groupId>

? <artifactId>aspectjweaver</artifactId>

? <version>1.8.9</version>

</dependency>

1

2

3

4

5

beans.xml 配置

添加命名空間

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

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

1

2

配置 Aop 代理

<aop:aspectj-autoproxy/>

1

編寫 aop 實現(xiàn)類

/**

* 聲明切面組件

*/@Component@AspectpublicclassLogCut{/**

? * 定義切入點 匹配方法規(guī)則定義

? * 匹配規(guī)則表達式含義 攔截 com.xxx.service 包下 以及子包下 所有類的所有方法

? */@Pointcut("execution (* com.xxx.service..*.*(..))")publicvoidcut(){}/**

? * 聲明前置通知 并將通知應(yīng)用到定義的切入點上

? * 目標類方法執(zhí)行前 執(zhí)行該通知

? */@Before(value="cut()")publicvoidbefore(){System.out.println("前置通知.....");}/**

? * 聲明返回通知 并將通知應(yīng)用到切入點上

? * 目標類方法執(zhí)行完畢執(zhí)行該通知

? */@AfterReturning(value="cut()")publicvoidafterReturning(){System.out.println("返回通知....");}/**

? * 聲明最終通知 并將通知應(yīng)用到切入點上

? * 目標類方法執(zhí)行過程中是否發(fā)生異常 均會執(zhí)行該通知 相當于異常中的 finally

? */@After(value="cut()")publicvoidafter(){System.out.println("最終通知....");}/**

? * 聲明異常通知 并將通知應(yīng)用到切入點上

? * 目標類方法執(zhí)行時發(fā)生異常 執(zhí)行該通知

? */@AfterThrowing(value="cut()",throwing="e")publicvoidafterThrowing(Exception e){System.out.println("異常通知....方法執(zhí)行異常時執(zhí)行:"+e);}/**

? * 聲明環(huán)繞通知 并將通知應(yīng)用到切入點上

? * 方法執(zhí)行前后 通過環(huán)繞通知定義相應(yīng)處理

? */@Around(value="cut()")publicObjectaround(ProceedingJoinPoint pjp)throwsThrowable{System.out.println("環(huán)繞前置...");System.out.println("環(huán)繞通知");System.out.println(pjp.getTarget()+"--"+pjp.getSignature());Object result=pjp.proceed();//執(zhí)行目標對象方法System.out.println("環(huán)繞后置...");returnresult;}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

Aop 匹配方法規(guī)則表達式語言(簡要了解)

Aop 切入點表達式簡介

執(zhí)行任意公共方法:

execution(public*(..))執(zhí)行任意的 set 方法execution(*set*(..))執(zhí)行 com.xxx.service 包下任意類的任意方法execution(*com.xxx.service.*.*(..))執(zhí)行 com.xxx.service 包 以及子包下任意類的任意方法execution(*com.xxx.service..*.*(..))

1

2

3

4

5

6

7

8

9

10

11

12

13

xml 方式

配置切面、切入點、通知

<!-- aop 相關(guān)配置 --><aop:config><!-- aop 切面配置 --><aop:aspectref="logCut"><!-- 定義 aop 切入點 --><aop:pointcutexpression="execution (* com.xxx.service..*.*(..))"id="cut"/><!-- 配置前置通知 指定前置通知方法名 并引用切入點定義 --><aop:beforemethod="before"pointcut-ref="cut"/><!-- 配置返回通知 指定返回通知方法名 并引用切入點定義 --><aop:after-returningmethod="afterReturning"pointcut-ref="cut"/><!-- 配置異常通知 指定異常通知方法名 并引用切入點定義 --><aop:after-throwingmethod="afterThrowing"throwing="e"pointcut-ref="cut"/><!-- 配置最終通知 指定最終通知方法名 并引用切入點定義 --><aop:aftermethod="after"pointcut-ref="cut"/><!-- 配置環(huán)繞通知 指定環(huán)繞通知方法名 并引用切入點定義 --><aop:aroundmethod="around"pointcut-ref="cut"/></aop:aspect></aop:config>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

定義 bean

/**

* 聲明切面組件

*/@ComponentpublicclassLogCut{publicvoidbefore(){System.out.println("前置通知.....");}publicvoidafterReturning(){System.out.println("返回通知....");}publicvoidafter(){System.out.println("最終通知....");}publicvoidafterThrowing(Exception e){System.out.println("異常通知....方法執(zhí)行異常時執(zhí)行:"+e);}publicObjectaround(ProceedingJoinPoint pjp)throwsThrowable{System.out.println("環(huán)繞前置...");System.out.println("環(huán)繞通知");System.out.println(pjp.getTarget()+"--"+pjp.getSignature());Object result=pjp.proceed();System.out.println("環(huán)繞后置...");returnresult;}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

擴展

AOP 的基本概念

JoinPoint(連接點)【動態(tài)】

被攔截到的每個點,spring 中指被攔截到的每一個方法,spring aop 一個連接點即代表一個方法的執(zhí)行。

Pointcut(切入點)【靜態(tài)】

對連接點進行攔截的定義(匹配規(guī)則定義 規(guī)定攔截哪些方法,對哪些方法進行處理),spring 這塊有專門的表達式語言定義。

Advice(通知){重點}

攔截到每一個連接點即(每一個方法)前后所要做的操作

前置通知(前置增強)–before() 執(zhí)行方法前通知

返回通知(返回增強)–afterReturning 方法正常結(jié)束返回后的通知

異常拋出通知(異常拋出增強)–afetrThrow()

最終通知 --after 無論方法是否發(fā)生異常,均會執(zhí)行該通知

環(huán)繞通知 --around 包圍一個連接點(join point)的通知,如方法調(diào)用。這是最強大的一種通知類型。 環(huán)繞通知可以在方法調(diào)用前后完成自定義的行為。它也會選擇是否繼續(xù)執(zhí)行連接點或直接返回它們自己的返回值或拋出異常來結(jié)束執(zhí)行

Aspect(切面)

切入點與通知的結(jié)合,決定了切面的定義,切入點定義了要攔截哪些類的 哪些方法,通知則定義了攔截方法后要做什么,切面則是橫切關(guān)注點的抽象,與類相似,類是對物體特征的抽象,切面則是橫切關(guān)注點抽象。

Target(目標對象)

被代理的目標對象

Weave(織入)

將切面應(yīng)用到目標對象并生成代理對象的這個過程即為織入(過程)。

Introduction(引入)

在不修改原有應(yīng)用程序代碼的情況下,在程序運行期為類動態(tài)添加方法或者字段的過程稱為引入。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容