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

Java AOP面向切面編程的概念和實(shí)現(xiàn)方式

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

一、AOP 是什么?

AOP(Aspect-Oriented Programming),即面向切面編程。它是一種編程范式,與我們所熟悉的OOP(面向?qū)ο缶幊蹋┦?strong>互補(bǔ)的關(guān)系,而不是替代。

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

看下面的例子:

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

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

二、AOP 的核心概念與實(shí)現(xiàn)方式

核心概念

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

實(shí)現(xiàn)方式

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

  • 如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,默認(rèn)使用 JDK 動(dòng)態(tài)代理
  • 如果目標(biāo)對(duì)象沒有實(shí)現(xiàn)接口,則使用 CGLIB 庫生成子類進(jìn)行代理。

三、Spring AOP 的關(guān)鍵注解

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

四、實(shí)際場景與代碼示例

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

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

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實(shí)現(xiàn))

WaterUsageLoggerAspect.java - 用水量記錄切面

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

3. 配置類(Spring配置)

AppConfig.java - 應(yīng)用配置

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

4. 測(cè)試類(演示代碼)

HomeChoresTest.java - 家務(wù)測(cè)試

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("=== 開始家務(wù)活動(dòng) ===");
        // 洗碗活動(dòng)
        System.out.println("\n--- 洗碗 ---");
        washDish.fillWater(10);
        washDish.wash();
        // 打掃活動(dòng)
        System.out.println("\n--- 打掃 ---");
        cleanRoom.fillWater(15);
        cleanRoom.clean();
        System.out.println("\n=== 家務(wù)完成 ===");
        System.out.println("總用水量: " + waterLogger.getTotalWaterUsage() + "升");
        context.close();
    }
}

5. 預(yù)期輸出

運(yùn)行測(cè)試類后,預(yù)期輸出如下:

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

代碼說明

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

五、AOP 的常見應(yīng)用場景

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

總結(jié)

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

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

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

相關(guān)文章

  • Springboot整合Shiro實(shí)現(xiàn)登錄與權(quán)限校驗(yàn)詳細(xì)解讀

    Springboot整合Shiro實(shí)現(xiàn)登錄與權(quán)限校驗(yàn)詳細(xì)解讀

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

    JAVA實(shí)現(xiàn)賬戶取款和存款操作

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

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

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

    Spring攔截器HandlerInterceptor接口代碼解析

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

    Java程序員應(yīng)該遵守的10條紀(jì)律

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

    win10 JDK17+Maven3.8安裝全過程

    文章詳細(xì)介紹了如何在Windows系統(tǒng)上安裝和配置JDK 17和Maven 3.8,包括設(shè)置環(huán)境變量、驗(yàn)證安裝和配置Maven的本地倉庫和遠(yuǎn)程源
    2026-01-01
  • Mybatis基礎(chǔ)概念與高級(jí)應(yīng)用小結(jié)

    Mybatis基礎(chǔ)概念與高級(jí)應(yīng)用小結(jié)

    這篇文章主要介紹了Mybatis基礎(chǔ)回顧與高級(jí)應(yīng)用,本文內(nèi)容有點(diǎn)小長,希望大家耐心閱讀,此文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例

    Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例

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

    JWT + 攔截器實(shí)現(xiàn)無狀態(tài)登錄系統(tǒng)

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

    2025-08-08
  • 基于java ssm springboot實(shí)現(xiàn)選課推薦交流平臺(tái)系統(tǒng)

    基于java ssm springboot實(shí)現(xiàn)選課推薦交流平臺(tái)系統(tǒng)

    這篇文章主要介紹了選課推薦交流平臺(tái)系統(tǒng)是基于java ssm springboot來的實(shí)現(xiàn)的,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08

最新評(píng)論

颍上县| 海林市| 龙胜| 林西县| 金秀| 罗甸县| 昌图县| 宜城市| 南汇区| 湖北省| 南和县| 玉山县| 四会市| 从江县| 南京市| 徐汇区| 通辽市| 博乐市| 澜沧| 昭通市| 金平| 郁南县| 兴义市| 百色市| 阳江市| 和林格尔县| 佳木斯市| 淮安市| 仁化县| 连江县| 太原市| 广安市| 安塞县| 吉水县| 米脂县| 兰西县| 襄城县| 嵩明县| 长沙市| 从江县| 大关县|