欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中切面的使用方法舉例詳解

 更新時(shí)間:2025年03月10日 09:45:16   作者:心疼你的一切  
這篇文章主要介紹了Java中切面編程(AOP)的基本概念、原理及實(shí)現(xiàn)方式,AOP通過將橫切關(guān)注點(diǎn)模塊化為切面,使代碼更易于維護(hù)和擴(kuò)展,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在Java中,切面編程(Aspect-Oriented Programming, AOP)是一種編程范式,用于將橫切關(guān)注點(diǎn)(如日志記錄、事務(wù)管理、安全性等)從業(yè)務(wù)邏輯中分離出來。AOP通過將這些關(guān)注點(diǎn)模塊化為“切面”,使代碼更易于維護(hù)和擴(kuò)展。

一、概念和原理

基本概念

切面(Aspect):一個(gè)切面是一個(gè)模塊化的關(guān)注點(diǎn)集合,它包含了多個(gè)通知和切入點(diǎn)的定義。例如,日志切面會(huì)定義在哪些方法執(zhí)行前后進(jìn)行日志記錄。

通知(Advice):通知定義了在切入點(diǎn)執(zhí)行時(shí)要執(zhí)行的代碼邏輯,也就是在特定的連接點(diǎn)上執(zhí)行的操作。常見的通知類型有前置通知、后置通知、環(huán)繞通知等。

切入點(diǎn)(Pointcut):切入點(diǎn)用于定義哪些連接點(diǎn)(程序執(zhí)行過程中的特定位置,如方法調(diào)用、異常拋出等)會(huì)觸發(fā)通知的執(zhí)行。它可以通過方法名、類名、參數(shù)類型等條件進(jìn)行精確匹配。

連接點(diǎn)(Join point):連接點(diǎn)是程序執(zhí)行過程中可以插入切面的點(diǎn),例如方法調(diào)用、字段訪問等。在 Java 中,主要的連接點(diǎn)通常是方法調(diào)用。

AOP 實(shí)現(xiàn)方式及原理

1.基于代理的 AOP 實(shí)現(xiàn)(如 Spring AOP)

原理:Spring AOP 默認(rèn)使用代理模式來實(shí)現(xiàn) AOP 功能,有兩種代理方式:JDK 動(dòng)態(tài)代理和 CGLIB 代理。

JDK 動(dòng)態(tài)代理:當(dāng)目標(biāo)對象實(shí)現(xiàn)了接口時(shí),Spring AOP 會(huì)使用 JDK 動(dòng)態(tài)代理。它基于 Java 的 java.lang.reflect.Proxy 類和 java.lang.reflect.InvocationHandler 接口。在運(yùn)行時(shí),JDK 動(dòng)態(tài)代理會(huì)根據(jù)目標(biāo)對象實(shí)現(xiàn)的接口動(dòng)態(tài)生成一個(gè)代理類,該代理類實(shí)現(xiàn)了與目標(biāo)對象相同的接口。當(dāng)調(diào)用代理對象的方法時(shí),會(huì)觸發(fā) InvocationHandler 的 invoke() 方法,在該方法中可以插入切面邏輯。

CGLIB 代理:當(dāng)目標(biāo)對象沒有實(shí)現(xiàn)接口時(shí),Spring AOP 會(huì)使用 CGLIB 代理。CGLIB(Code Generation Library)是一個(gè)強(qiáng)大的、高性能的代碼生成庫,它通過繼承目標(biāo)對象的類來創(chuàng)建代理對象。在運(yùn)行時(shí),CGLIB 會(huì)動(dòng)態(tài)生成一個(gè)目標(biāo)對象的子類,并重寫目標(biāo)對象的方法,在重寫的方法中插入切面邏輯。

代碼如下:

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import java.lang.reflect.Method;

// 定義業(yè)務(wù)接口
interface BusinessService {
    void doBusiness();
}

// 實(shí)現(xiàn)業(yè)務(wù)接口
class BusinessServiceImpl implements BusinessService {
    @Override
    public void doBusiness() {
        System.out.println("執(zhí)行核心業(yè)務(wù)邏輯");
    }
}

// 定義前置通知
class MyBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置通知:在方法執(zhí)行前記錄日志");
    }
}

public class AOPProxyExample {
    public static void main(String[] args) {
        // 創(chuàng)建目標(biāo)對象
        BusinessService target = new BusinessServiceImpl();
        // 創(chuàng)建前置通知對象
        MyBeforeAdvice advice = new MyBeforeAdvice();
        // 創(chuàng)建代理工廠
        ProxyFactory proxyFactory = new ProxyFactory();
        // 設(shè)置目標(biāo)對象
        proxyFactory.setTarget(target);
        // 添加通知
        proxyFactory.addAdvice(advice);
        // 獲取代理對象
        BusinessService proxy = (BusinessService) proxyFactory.getProxy();
        // 調(diào)用代理對象的方法
        proxy.doBusiness();
    }
}

二、基于字節(jié)碼增強(qiáng)的 AOP 實(shí)現(xiàn)(如 AspectJ)

原理:AspectJ 是一個(gè)功能強(qiáng)大的 AOP 框架,它采用字節(jié)碼增強(qiáng)的方式來實(shí)現(xiàn) AOP。在編譯時(shí)或類加載時(shí),AspectJ 會(huì)修改目標(biāo)類的字節(jié)碼,將切面邏輯直接插入到目標(biāo)類的方法中。與基于代理的實(shí)現(xiàn)方式不同,字節(jié)碼增強(qiáng)不需要?jiǎng)?chuàng)建代理對象,而是直接在目標(biāo)類的字節(jié)碼中添加切面代碼,因此性能更高,并且可以處理更多的連接點(diǎn)。

編譯時(shí)織入:在編譯 Java 源代碼時(shí),AspectJ 編譯器(ajc)會(huì)對源代碼進(jìn)行處理,將切面邏輯織入到目標(biāo)類的字節(jié)碼中。這種方式需要使用 AspectJ 編譯器來編譯代碼。

類加載時(shí)織入:在類加載時(shí),通過 Java 的類加載器對目標(biāo)類的字節(jié)碼進(jìn)行修改,將切面邏輯織入其中。這種方式不需要使用 AspectJ 編譯器,只需要在運(yùn)行時(shí)配置類加載器即可。

代碼如下:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

// 定義切面類
@Aspect
public class LoggingAspect {
    // 定義切入點(diǎn)
    @Pointcut("execution(* com.example.BusinessService.*(..))")
    public void businessServiceMethods() {}

    // 定義前置通知
    @Before("businessServiceMethods()")
    public void beforeBusinessServiceMethod(JoinPoint joinPoint) {
        System.out.println("前置通知:在方法執(zhí)行前記錄日志,方法名:" + joinPoint.getSignature().getName());
    }
}

// 定義業(yè)務(wù)類
class BusinessService {
    public void doBusiness() {
        System.out.println("執(zhí)行核心業(yè)務(wù)邏輯");
    }
}

public class AspectJExample {
    public static void main(String[] args) {
        BusinessService service = new BusinessService();
        service.doBusiness();
    }
}

總結(jié) 

到此這篇關(guān)于Java中切面的使用方法的文章就介紹到這了,更多相關(guān)JAVA中切面使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring框架通過工廠創(chuàng)建Bean的三種方式實(shí)現(xiàn)

    Spring框架通過工廠創(chuàng)建Bean的三種方式實(shí)現(xiàn)

    這篇文章主要介紹了Spring框架通過工廠創(chuàng)建Bean的三種方式實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 解決javaBean規(guī)范導(dǎo)致json傳參首字母大寫將永遠(yuǎn)獲取不到問題

    解決javaBean規(guī)范導(dǎo)致json傳參首字母大寫將永遠(yuǎn)獲取不到問題

    這篇文章主要介紹了解決javaBean規(guī)范導(dǎo)致json傳參首字母大寫將永遠(yuǎn)獲取不到問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • logback標(biāo)記日志過濾器MarkerFilter源碼解讀

    logback標(biāo)記日志過濾器MarkerFilter源碼解讀

    這篇文章主要為大家介紹了logback標(biāo)記日志過濾器MarkerFilter源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Spring?Boot自定義?Starter并推送到遠(yuǎn)端公服的詳細(xì)代碼

    Spring?Boot自定義?Starter并推送到遠(yuǎn)端公服的詳細(xì)代碼

    這篇文章主要介紹了Spring?Boot自定義?Starter并推送到遠(yuǎn)端公服,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • 談?wù)凷pring AOP中@Aspect的高級(jí)用法示例

    談?wù)凷pring AOP中@Aspect的高級(jí)用法示例

    在Spring AOP中目前只有執(zhí)行方法這一個(gè)連接點(diǎn),下面這篇文章主要給大家介紹了關(guān)于Spring AOP中@Aspect的高級(jí)用法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • Java中調(diào)用Python的實(shí)現(xiàn)示例

    Java中調(diào)用Python的實(shí)現(xiàn)示例

    本文主要介紹了Java中調(diào)用Python的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Spring?Boot快速過濾出一次請求的所有日志

    Spring?Boot快速過濾出一次請求的所有日志

    這篇文章主要介紹了Spring?Boot快速過濾出一次請求的所有日志,本文講述了如何使用MDC工具來快速過濾一次請求的所有日志,并通過裝飾器模式使得MDC工具在異步線程里也能生效,需要的朋友可以參考下
    2022-11-11
  • Java中如何利用Set判斷List集合中是否有重復(fù)元素

    Java中如何利用Set判斷List集合中是否有重復(fù)元素

    在開發(fā)工作中,我們有時(shí)需要去判斷List集合中是否含有重復(fù)的元素,這時(shí)候我們不需要找出重復(fù)的元素,我們只需要返回一個(gè)?Boolean?類型就可以了,下面通過本文給大家介紹Java中利用Set判斷List集合中是否有重復(fù)元素,需要的朋友可以參考下
    2023-05-05
  • Java8 使用 stream().sorted()對List集合進(jìn)行排序的操作

    Java8 使用 stream().sorted()對List集合進(jìn)行排序的操作

    這篇文章主要介紹了Java8 使用 stream().sorted()對List集合進(jìn)行排序的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • SpringBoot中的自動(dòng)配置原理詳解

    SpringBoot中的自動(dòng)配置原理詳解

    這篇文章主要介紹了SpringBoot中的自動(dòng)配置原理詳解,springboot的自動(dòng)配置類直觀的表現(xiàn)就是通過一系列的注解,使得springboot項(xiàng)目在啟動(dòng)的時(shí)候從配置文件中加載需要自動(dòng)配置的類,注入容器中,需要的朋友可以參考下
    2024-01-01

最新評論