<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:請(qǐng)說(shuō)下Spring Aop 常見(jiàn)注解和執(zhí)行順序

          共 3997字,需瀏覽 8分鐘

           ·

          2022-02-25 16:46


          來(lái)源:juejin.cn/post/7062506923194581029


          Spring 一開(kāi)始最強(qiáng)大的就是 IOC / AOP 兩大核心功能,我們今天一起來(lái)學(xué)習(xí)一下 Spring AOP 常見(jiàn)注解和執(zhí)行順序。Spring Aop 的常用注解

          首先我們一起來(lái)回顧一下 Spring Aop 中常用的幾個(gè)注解:

          • @Before 前置通知:目標(biāo)方法之前執(zhí)行
          • @After 后置通知:目標(biāo)方法之后執(zhí)行(始終執(zhí)行)
          • @AfterReturning 返回之后通知:執(zhí)行方法結(jié)束之前執(zhí)行(異常不執(zhí)行)
          • @AfterThrowing 異常通知:出香異常后執(zhí)行
          • @Around 環(huán)繞通知:環(huán)繞目標(biāo)方法執(zhí)行

          常見(jiàn)問(wèn)題

          1、你肯定知道 Spring ?, 那說(shuō)說(shuō) Aop 的去全部通知順序, Spring Boot 或者 Spring Boot 2 對(duì) aop 的執(zhí)行順序影響?

          2、說(shuō)說(shuō)你在 AOP 中遇到的那些坑?

          示例代碼

          下面我們先快速構(gòu)建一個(gè) spring aop 的 demo 程序來(lái)一起討論 spring aop 中的一些細(xì)節(jié)。

          配置文件

          為了方便我直接使用 spring-boot 進(jìn)行快速的項(xiàng)目搭建,大家可以使用 idea 的spring-boot 項(xiàng)目快速創(chuàng)建功能,或者去 start.spring.io 上面去快速創(chuàng)建spring-boot 應(yīng)用。

          因?yàn)楸救私?jīng)常手動(dòng)去網(wǎng)上貼一些依賴導(dǎo)致,依賴沖突服務(wù)啟動(dòng)失敗等一些問(wèn)題。

          plugins?{
          ????id?'org.springframework.boot'?version?'2.6.3'
          ????id?'io.spring.dependency-management'?version?'1.0.11.RELEASE'
          ????id?'java'
          }

          group?'io.zhengsh'
          version?'1.0-SNAPSHOT'

          repositories?{
          ????mavenCentral()
          ????maven?{?url?'https://repo.spring.io/milestone'?}
          ????maven?{?url?'https://repo.spring.io/snapshot'?}
          }

          dependencies?{
          ????#?其實(shí)這里也可以不增加?web?配置,為了試驗(yàn)簡(jiǎn)單,大家請(qǐng)忽略?
          ????implementation?'org.springframework.boot:spring-boot-starter-web'
          ????implementation?'org.springframework.boot:spring-boot-starter-actuator'
          ????implementation?'org.springframework.boot:spring-boot-starter-aop'
          ????
          ????testImplementation?'org.springframework.boot:spring-boot-starter-test'
          }

          tasks.named('test')?{
          ????useJUnitPlatform()
          }

          接口類

          首先我們需要定義一個(gè)接口。我們這里可以再來(lái)回顧一下 JDK 的默認(rèn)代理實(shí)現(xiàn)的選擇:

          • 如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,則默認(rèn)采用JDK動(dòng)態(tài)代理
          • 如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)接口,則采用進(jìn)行動(dòng)態(tài)代理
          • 如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,且強(qiáng)制Cglib,則使用cglib代理

          這塊的邏輯在 DefaultAopProxyFactory 大家有興趣可以去看看。

          public?interface?CalcService?{

          ????public?int?div(int?x,?int?y);
          }

          實(shí)現(xiàn)類

          這里我門(mén)就簡(jiǎn)單一點(diǎn)做一個(gè)除法操作,可以模擬正常也可以很容易的模擬錯(cuò)誤。

          @Service
          public?class?CalcServiceImpl?implements?CalcService?{

          ????@Override
          ????public?int?div(int?x,?int?y)?{
          ????????int?result?=?x?/?y;
          ????????System.out.println("====> CalcServiceImpl 被調(diào)用了,我們的計(jì)算結(jié)果是:"?+?result);
          ????????return?result;
          ????}
          }

          aop 攔截器

          申明一個(gè)攔截器我們要為當(dāng)前對(duì)象增加 @Aspect 和 @Component ,筆者之前也是才踩過(guò)這樣的坑,只加了一個(gè)。

          其實(shí)這塊我剛開(kāi)始也不是很理解,但是我看了 Aspect 注解的定義我就清楚了

          這里面根本就沒(méi)有 Bean 的定義。所以我們還是乖乖的加上兩個(gè)注解。

          還有就是如果當(dāng)測(cè)試的時(shí)候需要開(kāi)啟Aop 的支持為配置類上增加@EnableAspectJAutoProxy 注解。

          其實(shí) Aop 使用就三個(gè)步驟:

          • 定義 Aspect 定義切面
          • 定義 Pointcut 就是定義我們切入點(diǎn)
          • 定義具體的通知,比如: @After, @Before 等。
          @Aspect
          @Component
          public?class?MyAspect?{

          ????@Pointcut("execution(*?io.zhengsh.spring.service.impl..*.*(..))")
          ????public?void?divPointCut()?{

          ????}

          ????@Before("divPointCut()")
          ????public?void?beforeNotify()?{
          ????????System.out.println("----===>>?@Before?我是前置通知");
          ????}

          ????@After("divPointCut")
          ????public?void?afterNotify()?{
          ????????System.out.println("----===>>?@After??我是后置通知");
          ????}

          ????@AfterReturning("divPointCut")
          ????public?void?afterReturningNotify()?{
          ????????System.out.println("----===>>?@AfterReturning?我是前置通知");
          ????}

          ????@AfterThrowing("divPointCut")
          ????public?void?afterThrowingNotify()?{
          ????????System.out.println("----===>>?@AfterThrowing?我是異常通知");
          ????}

          ????@Around("divPointCut")
          ????public?Object?around(ProceedingJoinPoint?proceedingJoinPoint)?throws?Throwable?{
          ????????Object?retVal;
          ????????System.out.println("----===>>?@Around?環(huán)繞通知之前?AAA");
          ????????retVal?=?proceedingJoinPoint.proceed();
          ????????System.out.println("----===>>?@Around?環(huán)繞通知之后?BBB");
          ????????return?retVal;
          ????}
          }

          測(cè)試類

          其實(shí)我這個(gè)測(cè)試類,雖然用了 @Test 注解,但是我這個(gè)類更加像一個(gè) main 方法把:如下所示:

          執(zhí)行結(jié)論

          結(jié)果記錄:spring 4.x, spring-boot 1.5.9

          無(wú)法現(xiàn)在依賴,所以無(wú)法試驗(yàn)

          我直接說(shuō)一下結(jié)論:Spring 4 中環(huán)繞通知是在最里面執(zhí)行的

          結(jié)果記錄:spring 版本5.3.15 springboot 版本2.6.3

          多切面的情況

          多個(gè)切面的情況下,可以通過(guò)@Order指定先后順序,數(shù)字越小,優(yōu)先級(jí)越高。如下圖所示:

          代理失效場(chǎng)景

          下面一種場(chǎng)景會(huì)導(dǎo)致 aop 代理失效,因?yàn)槲覀冊(cè)趫?zhí)行 a 方法的時(shí)候其實(shí)本質(zhì)是執(zhí)行 AServer#a 的方法攔截器(MethodInterceptor)鏈, 當(dāng)我們?cè)?a 方法內(nèi)直接執(zhí)行b(), 其實(shí)本質(zhì)就相當(dāng)于 this.b() , 這個(gè)時(shí)候由執(zhí)行 a方法是調(diào)用到 a 的原始對(duì)象相當(dāng)于是 this 調(diào)用,那么會(huì)導(dǎo)致 b() 方法的代理失效。這個(gè)問(wèn)題也是我們開(kāi)發(fā)者在開(kāi)發(fā)過(guò)程中最常遇到的一個(gè)問(wèn)題。

          @Service
          public?class?AService?{
          ????
          ????public?void?a()?{
          ????????System.out.println("......?a");
          ????????b();
          ????}
          ????
          ????public?void?b()?{
          ????????System.out.println("......?b");
          ????}

          }

          程序汪資料鏈接

          程序汪接的7個(gè)私活都在這里,經(jīng)驗(yàn)整理

          Java項(xiàng)目分享 最新整理全集,找項(xiàng)目不累啦 06版

          堪稱神級(jí)的Spring Boot手冊(cè),從基礎(chǔ)入門(mén)到實(shí)戰(zhàn)進(jìn)階

          臥槽!字節(jié)跳動(dòng)《算法中文手冊(cè)》火了,完整版 PDF 開(kāi)放下載!

          臥槽!阿里大佬總結(jié)的《圖解Java》火了,完整版PDF開(kāi)放下載!

          字節(jié)跳動(dòng)總結(jié)的設(shè)計(jì)模式 PDF 火了,完整版開(kāi)放下載!

          歡迎添加程序汪個(gè)人微信 itwang008? 進(jìn)粉絲群或圍觀朋友圈

          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一道本在线无码免费视频 | 久久黄色五月 | 男女av在线观看 男女操逼黄片视频 | 伊人色色综合 | 中日韩欧美一级片 |