最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解Spring Aop @After(后置通知)的使用場景

 更新時(shí)間:2025年06月20日 09:09:23   作者:冰糖心書房  
@After 是 Spring AOP 中的另一種通知(Advice)類型,通常被稱為“后置通知”或“最終通知”,本文將通過詳細(xì)的代碼示例給大家介紹一下Spring Aop @After(后置通知)的使用場景,需要的朋友可以參考下

核心定義

@After 是 Spring AOP 中的另一種通知(Advice)類型,通常被稱為“后置通知”或“最終通知”。

它的核心作用是:

無論目標(biāo)方法是正常執(zhí)行完成,還是在執(zhí)行過程中拋出了異常,@After 通知中的代碼 總是 會(huì)在目標(biāo)方法執(zhí)行之后被執(zhí)行。

最經(jīng)典的類比就是 Java 中的 try...catch...finally 語句塊里的 finally 部分。@After 的行為和 finally 塊的行為幾乎一模一樣。

@After 通知的執(zhí)行流程

為了更好地理解,我們來看兩種情況下的執(zhí)行順序:

情況一:目標(biāo)方法成功執(zhí)行

  • @Before 通知執(zhí)行。
  • 目標(biāo)方法 (targetMethod()) 執(zhí)行并正常返回。
  • @After 通知執(zhí)行。
  • (如果定義了)@AfterReturning 通知執(zhí)行。

情況二:目標(biāo)方法拋出異常

  • @Before 通知執(zhí)行。
  • 目標(biāo)方法 (targetMethod()) 執(zhí)行,中途拋出異常。
  • @After 通知執(zhí)行。
  • (如果定義了)@AfterThrowing 通知執(zhí)行。
  • 異常繼續(xù)向上層調(diào)用棧拋出。

一個(gè)非常關(guān)鍵的點(diǎn)是:@After 通知本身無法訪問目標(biāo)方法的返回值(因?yàn)樗赡芨緵]有返回值,比如拋異常時(shí)),也無法捕獲或處理從目標(biāo)方法中拋出的異常。它只是一個(gè)保證“最后一定會(huì)被執(zhí)行”的鉤子。

@After 通知能做什么?(主要應(yīng)用場景)

后置通知非常適合執(zhí)行那些必須進(jìn)行的“清理”或“收尾”工作,無論業(yè)務(wù)邏輯成功與否。

資源釋放 (Resource Cleanup)

  • 這是 @After 最重要、最常見的用途。類似于 finally 塊。
  • 示例:釋放文件句柄、關(guān)閉網(wǎng)絡(luò)連接、關(guān)閉數(shù)據(jù)庫連接池中的連接等。確保即使業(yè)務(wù)代碼出錯(cuò),關(guān)鍵資源也不會(huì)被泄露。

上下文清理 (Context Cleanup)

  • 如果在 @Before 通知中向 ThreadLocal 存放了數(shù)據(jù),那么在 @After 通知中將其 remove() 是一個(gè)最佳實(shí)踐。這可以防止在線程池環(huán)境中發(fā)生內(nèi)存泄漏或數(shù)據(jù)錯(cuò)亂。

最終日志記錄 (Final Auditing)

  • 記錄一個(gè)操作的結(jié)束。
  • 示例:“方法 updateProduct 執(zhí)行完畢。” 這個(gè)日志不關(guān)心成功或失敗,只記錄“結(jié)束”這個(gè)事實(shí)。

性能監(jiān)控 (Performance Monitoring)

  • 可以在 @Before 中記錄一個(gè)開始時(shí)間,然后在 @After 中記錄結(jié)束時(shí)間,并計(jì)算總耗時(shí)。

示例:

  • @Before: long startTime = System.currentTimeMillis(); (存入 ThreadLocal)
  • @After: long endTime = System.currentTimeMillis(); long duration = endTime - startTime; log.info("方法耗時(shí): {} ms", duration);

與 @AfterReturning 和 @AfterThrowing 的區(qū)別

這是新手很容易混淆的地方,理解它們的區(qū)別至關(guān)重要:

知類型執(zhí)行時(shí)機(jī)能否訪問返回值?能否訪問異常?主要用途
@After (最終通知)總是在目標(biāo)方法后執(zhí)行(無論成功或失?。?/td>不能不能資源清理、最終日志
@AfterReturning (返回通知)僅在目標(biāo)方法成功執(zhí)行后執(zhí)行可以不適用基于返回結(jié)果的附加操作
@AfterThrowing (異常通知)僅在目標(biāo)方法拋出異常后執(zhí)行不適用可以異常日志記錄、告警通知

簡單來說:

  • 總是執(zhí)行清理?用 @After。
  • 想在成功后根據(jù)返回值做點(diǎn)事?用 @AfterReturning。
  • 想在失敗后專門處理異常?用 @AfterThrowing。

代碼示例

我們擴(kuò)展之前的例子,增加一個(gè)刪除方法(可能會(huì)失?。?,并為所有方法添加 @After 通知。

1. 業(yè)務(wù)服務(wù)類 (目標(biāo)對象)

package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    // 成功執(zhí)行的例子
    public String findUserById(Long id) {
        System.out.println("--- 核心業(yè)務(wù)邏輯:正在根據(jù) ID 查詢用戶... ---");
        return "User" + id;
    }

    // 拋出異常的例子
    public void deleteUser(Long id) {
        System.out.println("--- 核心業(yè)務(wù)邏輯:正在嘗試刪除用戶... ---");
        if (id <= 0) {
            throw new IllegalArgumentException("用戶ID無效,刪除失?。?);
        }
        System.out.println("用戶 " + id + " 已被成功刪除。");
    }
}

2. 切面類 (Aspect) 中定義 @After 通知

package com.example.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Aspect
@Component
public class LoggingAspect {

    @Pointcut("execution(public * com.example.service.*.*(..))")
    public void serviceLayerPointcut() {}

    // 前置通知
    @Before("serviceLayerPointcut()")
    public void logBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("==================================================");
        System.out.printf("[AOP 前置通知]: 方法 [%s] 即將執(zhí)行... 參數(shù): %s%n", methodName, Arrays.toString(args));
    }

    // 后置通知 (最終通知)
    @After("serviceLayerPointcut()")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.printf("[AOP 后置通知]: 方法 [%s] 執(zhí)行完畢。執(zhí)行清理工作...%n", methodName);
        System.out.println("--------------------------------------------------\n");
    }
}

3. 運(yùn)行代碼并觀察輸出

調(diào)用成功的方法 userService.findUserById(101L):

==================================================
[AOP 前置通知]: 方法 [findUserById] 即將執(zhí)行... 參數(shù): [101]
--- 核心業(yè)務(wù)邏輯:正在根據(jù) ID 查詢用戶... ---
[AOP 后置通知]: 方法 [findUserById] 執(zhí)行完畢。執(zhí)行清理工作...
--------------------------------------------------

@After 在方法成功后執(zhí)行了。

調(diào)用失敗的方法 userService.deleteUser(0L) (需要用 try-catch 捕獲異常):

try {
    userService.deleteUser(0L);
} catch (Exception e) {
    System.err.println("在調(diào)用方捕獲到異常: " + e.getMessage());
}

輸出:

==================================================
[AOP 前置通知]: 方法 [deleteUser] 即將執(zhí)行... 參數(shù): [0]
--- 核心業(yè)務(wù)邏輯:正在嘗試刪除用戶... ---
[AOP 后置通知]: 方法 [deleteUser] 執(zhí)行完畢。執(zhí)行清理工作...
--------------------------------------------------

在調(diào)用方捕獲到異常: 用戶ID無效,刪除失??!

即使 deleteUser 拋出了異常,@After 通知 (logAfter 方法) 依然被執(zhí)行了,完美地展示了其 finally 的特性。

總結(jié)

特性描述
執(zhí)行時(shí)機(jī)無論成功或失敗,總是在目標(biāo)方法執(zhí)行之后執(zhí)行。
核心用途資源釋放、上下文清理、最終日志記錄等收尾工作。
行為類似Java 的 finally 語句塊。
關(guān)鍵限制無法訪問目標(biāo)方法的返回值,也無法捕獲或修改異常。
關(guān)鍵參數(shù)可以注入 JoinPoint 對象,獲取方法元數(shù)據(jù)。

以上就是一文詳解Spring Aop @After(后置通知)的使用場景的詳細(xì)內(nèi)容,更多關(guān)于Spring Aop @After使用場景的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于JVM 中常見垃圾收集算法介紹

    基于JVM 中常見垃圾收集算法介紹

    下面小編就為大家分享一篇基于JVM 中常見垃圾收集算法介紹,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • SpringMVC和Ajax的交互詳解(手工處理)

    SpringMVC和Ajax的交互詳解(手工處理)

    Ajax即異步的?JavaScript和XML,是一種無需重新加載整個(gè)網(wǎng)頁的情況下,能夠更新部分模塊的網(wǎng)頁技術(shù),下面這篇文章主要給大家介紹了關(guān)于SpringMVC和Ajax交互的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • java新手入門——String類詳解

    java新手入門——String類詳解

    在java、C#中,String類是不可變的,對String類的任何改變,都是返回一個(gè)新的String類對象。string>是C++標(biāo)準(zhǔn)程序庫中的一個(gè)頭文件
    2021-06-06
  • Java集合框架概覽之ArrayList源碼刨析

    Java集合框架概覽之ArrayList源碼刨析

    本文主要從一個(gè)簡單的代碼入手,對ArrayList?的最常用的源碼進(jìn)行刨析,文中源碼摘自?JDK1.8,源碼的注釋部分博主也加入了自己的翻譯,歡迎讀者食用
    2023-03-03
  • Java使用ffmpeg和mencoder實(shí)現(xiàn)視頻轉(zhuǎn)碼

    Java使用ffmpeg和mencoder實(shí)現(xiàn)視頻轉(zhuǎn)碼

    這篇文章主要為大家詳細(xì)介紹了Java使用ffmpeg和mencoder實(shí)現(xiàn)視頻轉(zhuǎn)碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Java裝飾者模式的示例詳解

    Java裝飾者模式的示例詳解

    裝飾者模式:在不改變原有對象的基礎(chǔ)之上,動(dòng)態(tài)的將功能附加到對象上,提供了繼承更有彈性的替代方案,也體現(xiàn)了開閉原則。本文將通過示例詳細(xì)講解一下裝飾者模式,需要的可以參考一下
    2022-02-02
  • Java十分鐘精通類?封裝?繼承

    Java十分鐘精通類?封裝?繼承

    基礎(chǔ)不牢地動(dòng)山搖,類、封裝、繼承是我們在學(xué)習(xí)基礎(chǔ)時(shí)必然要碰到的知識(shí)點(diǎn),讓我們一起來學(xué)習(xí)或回顧一下,感興趣的伙伴來看看吧
    2022-03-03
  • MyBatis自定義typeHandler的完整實(shí)例

    MyBatis自定義typeHandler的完整實(shí)例

    這篇文章主要給大家介紹了關(guān)于MyBatis自定義typeHandler的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用MyBatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 如何在Java Deeplearning4j中進(jìn)行數(shù)據(jù)加載與預(yù)處理

    如何在Java Deeplearning4j中進(jìn)行數(shù)據(jù)加載與預(yù)處理

    本文介紹了如何在 Deeplearning4j 中加載和預(yù)處理數(shù)據(jù),包括圖像和 CSV 數(shù)據(jù)的加載,以及基本的數(shù)據(jù)標(biāo)準(zhǔn)化和分割操作,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • Java超詳細(xì)講解三大特性之一的多態(tài)

    Java超詳細(xì)講解三大特性之一的多態(tài)

    多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量到底會(huì)指向哪個(gè)類的實(shí)例對象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定
    2022-05-05

最新評論

逊克县| 万州区| 巫山县| 承德市| 方正县| 密云县| 库尔勒市| 汝南县| 虎林市| 阿拉善右旗| 青阳县| 长子县| 湟源县| 利川市| 沙湾县| 抚顺市| 文山县| 长岭县| 莱州市| 普兰店市| 马龙县| 娱乐| 绥宁县| 普格县| 葵青区| 龙岩市| 宝鸡市| 安新县| 秦皇岛市| 昌乐县| 宁海县| 资阳市| 亚东县| 禄丰县| 锦屏县| 河源市| 宣恩县| 乐安县| 阿拉善右旗| 怀宁县| 玉树县|