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

Java AOP面向切面編程的概念和實現方式

 更新時間:2025年09月30日 14:43:08   作者:talenteddriver  
AOP是面向切面編程,通過動態(tài)代理將橫切關注點(如日志、事務)與核心業(yè)務邏輯分離,提升代碼復用性和可維護性,本文給大家介紹Java AOP面向切面編程的概念和實現方式,感興趣的朋友一起看看吧

一、AOP 是什么?

AOP(Aspect-Oriented Programming),即面向切面編程。它是一種編程范式,與我們所熟悉的OOP(面向對象編程)是互補的關系,而不是替代。

  • OOP 的局限:OOP的核心是對象,它擅長將功能進行縱向的模塊化劃分(例如,UserService類負責用戶相關所有邏輯)。但對于一些需要橫向地散布 across 多個模塊的功能,OOP就顯得力不從心。
    • 例如:日志記錄、性能監(jiān)控、事務管理、安全校驗。這些邏輯幾乎需要出現在每一個業(yè)務方法中,但它們本質上又不屬于核心業(yè)務邏輯。
  • AOP 的解決方案:AOP將這些散布在各處的橫切關注點(Cross-Cutting Concerns)從核心業(yè)務邏輯中分離出來,封裝成一個獨立的可重用的模塊,稱為切面(Aspect)。然后,在程序運行的合適時機,AOP會自動地將這些切面代碼“織入”到需要它們的方法中。

看下面的例子:

面向對象編程OPP完成了穿衣、吃飯、洗碗等這些功能,但從另一個維度去控制這些功能,比如“查看穿衣服、吃飯的時間(性能監(jiān)控)”、“保證吃飯、洗碗連在一起完成(事務管理)”、“記錄洗碗、打掃消耗的用水量(日志記錄)”這些就是面向切面編程AOP

  • 沒有AOP,就得在每個功能上添加相應控制,比如在穿衣服寫一遍記錄時間的代碼,然后再再吃飯?zhí)帉懸槐橛涗洉r間的代碼。這顯然不合理。AOP讓核心業(yè)務(穿衣、吃飯)和通用功能(記錄時間)得以解耦。

二、AOP 的核心概念與實現方式

核心概念

  • Aspect(切面):封裝橫切關注點的模塊。它是一個類,上面標注了 @Aspect 注解。例如:LoggingAspect(日志切面)、TransactionAspect(事務切面)。
  • Advice(通知):切面中的具體方法。它定義了“做什么”以及“何時做”。
  • 何時做@Before(方法前)、@After(方法后)、@AfterReturning(成功返回后)、@AfterThrowing(拋出異常后)、@Around(環(huán)繞,最強大)。
  • Pointcut(切點):一個表達式,定義了“在何處做”,即匹配哪些類的哪些方法需要被增強。它決定了Advice的應用位置。
  • Join Point(連接點):程序執(zhí)行過程中能夠插入切面的一個點,例如方法調用、異常拋出等。在Spring AOP中,連接點總是代表一個方法的執(zhí)行。
  • Weaving(織入):將切面代碼應用到目標對象,從而創(chuàng)建代理對象的過程。Spring AOP在運行時通過動態(tài)代理完成織入。

實現方式

Spring AOP 的底層就是基于我們之前討論過的動態(tài)代理

  • 如果目標對象實現了接口,默認使用 JDK 動態(tài)代理。
  • 如果目標對象沒有實現接口,則使用 CGLIB 庫生成子類進行代理。

三、Spring AOP 的關鍵注解

注解說明
@Aspect聲明一個類是切面。
@Pointcut聲明一個切點表達式,可被通知方法引用,避免重復書寫。
@Before前置通知:在目標方法執(zhí)行之前執(zhí)行。
@AfterReturning返回通知:在目標方法成功執(zhí)行并返回后執(zhí)行。
@AfterThrowing異常通知:在目標方法拋出異常后執(zhí)行。
@After后置通知:在目標方法執(zhí)行之后執(zhí)行(無論成功還是異常,類似于finally)。
@Around環(huán)繞通知:最強大的通知類型,可以手動控制目標方法的執(zhí)行時機,可以在方法執(zhí)行前后添加自定義行為。

四、實際場景與代碼示例

場景一:記錄洗碗和打掃的用水量

1. 業(yè)務類(核心方法)

WashDish.java - 洗碗類

@Component
public class WashDish {
    private int water;
    public int fillWater(int amount) {
        this.water += amount;
        System.out.println("洗碗接水: " + amount + "升");
        return amount;
    }
    public void wash() {
        System.out.println("使用" + water + "升水洗碗");
        water = 0;
    }
}

CleanRoom.java - 打掃類

@Component
public class CleanRoom {
    private int water;
    public int fillWater(int amount) {
        this.water += amount;
        System.out.println("打掃接水: " + amount + "升");
        return amount;
    }
    public void clean() {
        System.out.println("使用" + water + "升水打掃房間");
        water = 0;
    }
}

2. 切面類(AOP實現)

WaterUsageLoggerAspect.java - 用水量記錄切面

/**
* 切面類
*/
@Aspect
@Component
public class WaterUsageLoggerAspect {
    private Map<String, Integer> waterUsageRecords = new HashMap<>();
    /**
     * 切入點:規(guī)定哪些類被控制
     */
    @Pointcut("execution(* WashDish.fillWater(..)) || execution(* CleanRoom.fillWater(..))")
    public void waterUsagePointcut() {}
    /**
     * 通知
     */
    @AfterReturning(pointcut = "waterUsagePointcut()", returning = "waterAmount")
    public void logWaterUsage(int waterAmount) {
        String activity = "家務活動";
        waterUsageRecords.put(activity, waterUsageRecords.getOrDefault(activity, 0) + waterAmount);
        System.out.println("記錄用水: " + waterAmount + "升,當前總用水量: " + waterUsageRecords.get(activity) + "升");
    }
    public int getTotalWaterUsage() {
        return waterUsageRecords.values().stream().mapToInt(Integer::intValue).sum();
    }
}

3. 配置類(Spring配置)

AppConfig.java - 應用配置

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.example.aop")
public class AppConfig {
}

4. 測試類(演示代碼)

HomeChoresTest.java - 家務測試

public class HomeChoresTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(AppConfig.class);
        WashDish washDish = context.getBean(WashDish.class);
        CleanRoom cleanRoom = context.getBean(CleanRoom.class);
        WaterUsageLoggerAspect waterLogger = context.getBean(WaterUsageLoggerAspect.class);
        System.out.println("=== 開始家務活動 ===");
        // 洗碗活動
        System.out.println("\n--- 洗碗 ---");
        washDish.fillWater(10);
        washDish.wash();
        // 打掃活動
        System.out.println("\n--- 打掃 ---");
        cleanRoom.fillWater(15);
        cleanRoom.clean();
        System.out.println("\n=== 家務完成 ===");
        System.out.println("總用水量: " + waterLogger.getTotalWaterUsage() + "升");
        context.close();
    }
}

5. 預期輸出

運行測試類后,預期輸出如下:

=== 開始家務活動 === 
--- 洗碗 --- 
洗碗接水: 10升 
記錄用水: 10升,當前總用水量: 10升 
使用10升水洗碗 
--- 打掃 --- 
打掃接水: 15升 
記錄用水: 15升,當前總用水量: 25升 
使用15升水打掃房間 
=== 家務完成 === 總用水量: 25升

代碼說明

  • 業(yè)務類:包含核心的家務邏輯(洗碗和打掃),每個類都有一個fillWater方法用于接水。
  • 切面類
    • 使用@Aspect注解標記為切面
    • 使用@Pointcut定義切入點,匹配所有接水操作
    • 使用@AfterReturning后置通知記錄用水量
    • 維護用水記錄并提供查詢接口
  • 配置類:啟用Spring AOP自動代理和組件掃描
  • 測試類:演示如何使用AOP記錄家務活動的用水量

五、AOP 的常見應用場景

  • 日志記錄:如上例,記錄方法入參、出參、執(zhí)行耗時,用于調試和監(jiān)控。
  • 事務管理這是最經典的應用! Spring的 @Transactional 注解就是基于AOP實現的。它在方法開始時開啟事務,在方法成功執(zhí)行后提交事務,在拋出異常時回滾事務。
  • 權限校驗和安全控制:在方法執(zhí)行前,判斷當前用戶是否有權限執(zhí)行此操作。例如使用 @PreAuthorize 注解。
  • 性能監(jiān)控:統計方法的執(zhí)行時間,上報給監(jiān)控系統,用于發(fā)現性能瓶頸。
  • 異常處理與統一返回:捕獲服務層拋出的異常,將其轉換為友好的錯誤信息格式返回給前端。
  • 緩存:在方法執(zhí)行前檢查緩存中是否有數據,如果有則直接返回,否則執(zhí)行方法并將結果放入緩存。

總結

  • AOP是什么:一種將橫切關注點(日志、事務等)與核心業(yè)務邏輯分離的技術。
  • 如何實現:Spring AOP通過動態(tài)代理在運行時將切面“織入”到目標方法中。
  • 核心注解@Aspect, @Pointcut, @Around, @Before, @After等。
  • 為何需要:實現解耦、提高代碼的可復用性可維護性,讓開發(fā)者能更專注于核心業(yè)務邏輯。

通過AOP,我們可以以一種非常優(yōu)雅和非侵入式的方式,為應用程序添加強大的功能。

到此這篇關于java:AOP面向切面編程的文章就介紹到這了,更多相關java aop切面內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Springboot整合Shiro實現登錄與權限校驗詳細解讀

    Springboot整合Shiro實現登錄與權限校驗詳細解讀

    本文給大家介紹Springboot整合Shiro的基本使用,Apache?Shiro是Java的一個安全框架,Shiro本身無法知道所持有令牌的用戶是否合法,我們將整合Shiro實現登錄與權限的驗證
    2022-04-04
  • JAVA實現賬戶取款和存款操作

    JAVA實現賬戶取款和存款操作

    這篇文章主要介紹了JAVA實現賬戶取款和存款操作,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • 詳解SpringBoot如何正確解析日期格式

    詳解SpringBoot如何正確解析日期格式

    這篇文章主要介紹了SpringBoot如何正確解析日期格式,文中給出了兩種解決方案,通過代碼示例講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • Spring攔截器HandlerInterceptor接口代碼解析

    Spring攔截器HandlerInterceptor接口代碼解析

    這篇文章主要介紹了Spring攔截器HandlerInterceptor接口代碼解析,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • Java程序員應該遵守的10條紀律

    Java程序員應該遵守的10條紀律

    Java程序員有許多應遵循的守則或最佳實踐方式。本文概述了每個開發(fā)者最應該遵循的10條守則或戒律,如果不遵循它們,將會導致災難性后果。
    2015-09-09
  • win10 JDK17+Maven3.8安裝全過程

    win10 JDK17+Maven3.8安裝全過程

    文章詳細介紹了如何在Windows系統上安裝和配置JDK 17和Maven 3.8,包括設置環(huán)境變量、驗證安裝和配置Maven的本地倉庫和遠程源
    2026-01-01
  • Mybatis基礎概念與高級應用小結

    Mybatis基礎概念與高級應用小結

    這篇文章主要介紹了Mybatis基礎回顧與高級應用,本文內容有點小長,希望大家耐心閱讀,此文結合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-06-06
  • Java使用Socket判斷某服務能否連通代碼實例

    Java使用Socket判斷某服務能否連通代碼實例

    這篇文章主要介紹了Java使用Socket判斷某服務能否連通代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • JWT + 攔截器實現無狀態(tài)登錄系統

    JWT + 攔截器實現無狀態(tài)登錄系統

    JWT(JSON Web Token)提供了一種無狀態(tài)的解決方案:用戶登錄后,服務器返回一個 Token,后續(xù)請求攜帶該 Token 即可完成身份驗證,無需服務器存儲會話信息,本文將結合 Spring Boot 攔截器,手把手實現一個完整的JWT無狀態(tài)登錄系統,感興趣的朋友一起看看吧

    2025-08-08
  • 基于java ssm springboot實現選課推薦交流平臺系統

    基于java ssm springboot實現選課推薦交流平臺系統

    這篇文章主要介紹了選課推薦交流平臺系統是基于java ssm springboot來的實現的,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08

最新評論

景谷| 华安县| 登封市| 交城县| 集贤县| 常德市| 芜湖县| 连平县| 宣武区| 龙口市| 会东县| 太白县| 新营市| 辽宁省| 兴国县| 乳山市| 林西县| 油尖旺区| 河间市| 宜州市| 庆阳市| 府谷县| 北海市| 文化| 苗栗县| 凤阳县| 清流县| 抚州市| 信丰县| 安岳县| 双柏县| 阳新县| 行唐县| 麟游县| 宁城县| 丹巴县| 满城县| 清镇市| 贺州市| 惠东县| 陵川县|