国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

spring6-AOP面向切面編程

這篇具有很好參考價(jià)值的文章主要介紹了spring6-AOP面向切面編程。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1、場(chǎng)景模擬

搭建子模塊:spring6-aop

1.1、聲明接口

聲明計(jì)算器接口Calculator,包含加減乘除的抽象方法

public interface Calculator {
    
    int add(int i, int j);
    
    int sub(int i, int j);
    
    int mul(int i, int j);
    
    int div(int i, int j);
    
}
1.2、創(chuàng)建實(shí)現(xiàn)類

spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

public class CalculatorImpl implements Calculator {
    
    @Override
    public int add(int i, int j) {
    
        int result = i + j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
    
    @Override
    public int sub(int i, int j) {
    
        int result = i - j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
    
    @Override
    public int mul(int i, int j) {
    
        int result = i * j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
    
    @Override
    public int div(int i, int j) {
    
        int result = i / j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
}
1.3、創(chuàng)建帶日志功能的實(shí)現(xiàn)類

spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

public class CalculatorLogImpl implements Calculator {
    
    @Override
    public int add(int i, int j) {
    
        System.out.println("[日志] add 方法開始了,參數(shù)是:" + i + "," + j);
    
        int result = i + j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        System.out.println("[日志] add 方法結(jié)束了,結(jié)果是:" + result);
    
        return result;
    }
    
    @Override
    public int sub(int i, int j) {
    
        System.out.println("[日志] sub 方法開始了,參數(shù)是:" + i + "," + j);
    
        int result = i - j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        System.out.println("[日志] sub 方法結(jié)束了,結(jié)果是:" + result);
    
        return result;
    }
    
    @Override
    public int mul(int i, int j) {
    
        System.out.println("[日志] mul 方法開始了,參數(shù)是:" + i + "," + j);
    
        int result = i * j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        System.out.println("[日志] mul 方法結(jié)束了,結(jié)果是:" + result);
    
        return result;
    }
    
    @Override
    public int div(int i, int j) {
    
        System.out.println("[日志] div 方法開始了,參數(shù)是:" + i + "," + j);
    
        int result = i / j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        System.out.println("[日志] div 方法結(jié)束了,結(jié)果是:" + result);
    
        return result;
    }
}
1.4、提出問題

①現(xiàn)有代碼缺陷

針對(duì)帶日志功能的實(shí)現(xiàn)類,我們發(fā)現(xiàn)有如下缺陷:

  • 對(duì)核心業(yè)務(wù)功能有干擾,導(dǎo)致程序員在開發(fā)核心業(yè)務(wù)功能時(shí)分散了精力
  • 附加功能分散在各個(gè)業(yè)務(wù)功能方法中,不利于統(tǒng)一維護(hù)

②解決思路

解決這兩個(gè)問題,核心就是:解耦。我們需要把附加功能從業(yè)務(wù)功能代碼中抽取出來。

③困難

解決問題的困難:要抽取的代碼在方法內(nèi)部,靠以前把子類中的重復(fù)代碼抽取到父類的方式?jīng)]法解決。所以需要引入新的技術(shù)。

2、代理模式

2.1、概念

①介紹

二十三種設(shè)計(jì)模式中的一種,屬于結(jié)構(gòu)型模式。它的作用就是通過提供一個(gè)代理類,讓我們?cè)谡{(diào)用目標(biāo)方法的時(shí)候,不再是直接對(duì)目標(biāo)方法進(jìn)行調(diào)用,而是通過代理類間接調(diào)用。讓不屬于目標(biāo)方法核心邏輯的代碼從目標(biāo)方法中剝離出來——解耦。調(diào)用目標(biāo)方法時(shí)先調(diào)用代理對(duì)象的方法,減少對(duì)目標(biāo)方法的調(diào)用和打擾,同時(shí)讓附加功能能夠集中在一起也有利于統(tǒng)一維護(hù)。
spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程
spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程
②生活中的代理

  • 廣告商找大明星拍廣告需要經(jīng)過經(jīng)紀(jì)人
  • 合作伙伴找大老板談合作要約見面時(shí)間需要經(jīng)過秘書
  • 房產(chǎn)中介是買賣雙方的代理

③相關(guān)術(shù)語

  • 代理:將非核心邏輯剝離出來以后,封裝這些非核心邏輯的類、對(duì)象、方法。
  • 目標(biāo):被代理“套用”了非核心邏輯代碼的類、對(duì)象、方法。
2.2、靜態(tài)代理

創(chuàng)建靜態(tài)代理類:

public class CalculatorStaticProxy implements Calculator {
    
    // 將被代理的目標(biāo)對(duì)象聲明為成員變量
    private Calculator target;
    
    public CalculatorStaticProxy(Calculator target) {
        this.target = target;
    }
    
    @Override
    public int add(int i, int j) {
    
        // 附加功能由代理類中的代理方法來實(shí)現(xiàn)
        System.out.println("[日志] add 方法開始了,參數(shù)是:" + i + "," + j);
    
        // 通過目標(biāo)對(duì)象來實(shí)現(xiàn)核心業(yè)務(wù)邏輯
        int addResult = target.add(i, j);
    
        System.out.println("[日志] add 方法結(jié)束了,結(jié)果是:" + addResult);
    
        return addResult;
    }
}

靜態(tài)代理確實(shí)實(shí)現(xiàn)了解耦,但是由于代碼都寫死了,完全不具備任何的靈活性。就拿日志功能來說,將來其他地方也需要附加日志,那還得再聲明更多個(gè)靜態(tài)代理類,那就產(chǎn)生了大量重復(fù)的代碼,日志功能還是分散的,沒有統(tǒng)一管理。

提出進(jìn)一步的需求:將日志功能集中到一個(gè)代理類中,將來有任何日志需求,都通過這一個(gè)代理類來實(shí)現(xiàn)。這就需要使用動(dòng)態(tài)代理技術(shù)了。

2.3、動(dòng)態(tài)代理

spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程
生產(chǎn)代理對(duì)象的工廠類:

public class ProxyFactory {

    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxy(){

        /**
         * newProxyInstance():創(chuàng)建一個(gè)代理實(shí)例
         * 其中有三個(gè)參數(shù):
         * 1、classLoader:加載動(dòng)態(tài)生成的代理類的類加載器
         * 2、interfaces:目標(biāo)對(duì)象實(shí)現(xiàn)的所有接口的class對(duì)象所組成的數(shù)組
         * 3、invocationHandler:設(shè)置代理對(duì)象實(shí)現(xiàn)目標(biāo)對(duì)象方法的過程,即代理類中如何重寫接口中的抽象方法
         */
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /**
                 * proxy:代理對(duì)象
                 * method:代理對(duì)象需要實(shí)現(xiàn)的方法,即其中需要重寫的方法
                 * args:method所對(duì)應(yīng)方法的參數(shù)
                 */
                Object result = null;
                try {
                    System.out.println("[動(dòng)態(tài)代理][日志] "+method.getName()+",參數(shù):"+ Arrays.toString(args));
                    result = method.invoke(target, args);
                    System.out.println("[動(dòng)態(tài)代理][日志] "+method.getName()+",結(jié)果:"+ result);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("[動(dòng)態(tài)代理][日志] "+method.getName()+",異常:"+e.getMessage());
                } finally {
                    System.out.println("[動(dòng)態(tài)代理][日志] "+method.getName()+",方法執(zhí)行完畢");
                }
                return result;
            }
        };

        return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    }
}
2.4、測(cè)試
@Test
public void testDynamicProxy(){
    ProxyFactory factory = new ProxyFactory(new CalculatorLogImpl());
    Calculator proxy = (Calculator) factory.getProxy();
    proxy.div(1,0);
    //proxy.div(1,1);
}

3、AOP概念及相關(guān)術(shù)語

3.1、概述

AOP(Aspect Oriented Programming)是一種設(shè)計(jì)思想,是軟件設(shè)計(jì)領(lǐng)域中的面向切面編程,它是面向?qū)ο缶幊痰囊环N補(bǔ)充和完善,它以通過預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理方式實(shí)現(xiàn),在不修改源代碼的情況下,給程序動(dòng)態(tài)統(tǒng)一添加額外功能的一種技術(shù)。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。

3.2、相關(guān)術(shù)語
①橫切關(guān)注點(diǎn)

分散在每個(gè)各個(gè)模塊中解決同一樣的問題,如用戶驗(yàn)證、日志管理、事務(wù)處理、數(shù)據(jù)緩存都屬于橫切關(guān)注點(diǎn)。

從每個(gè)方法中抽取出來的同一類非核心業(yè)務(wù)。在同一個(gè)項(xiàng)目中,我們可以使用多個(gè)橫切關(guān)注點(diǎn)對(duì)相關(guān)方法進(jìn)行多個(gè)不同方面的增強(qiáng)。

這個(gè)概念不是語法層面的,而是根據(jù)附加功能的邏輯上的需要:有十個(gè)附加功能,就有十個(gè)橫切關(guān)注點(diǎn)。

spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

②通知(增強(qiáng))

增強(qiáng),通俗說,就是你想要增強(qiáng)的功能,比如 安全,事務(wù),日志等。

每一個(gè)橫切關(guān)注點(diǎn)上要做的事情都需要寫一個(gè)方法來實(shí)現(xiàn),這樣的方法就叫通知方法。

  • 前置通知:在被代理的目標(biāo)方法執(zhí)行
  • 返回通知:在被代理的目標(biāo)方法成功結(jié)束后執(zhí)行(壽終正寢
  • 異常通知:在被代理的目標(biāo)方法異常結(jié)束后執(zhí)行(死于非命
  • 后置通知:在被代理的目標(biāo)方法最終結(jié)束后執(zhí)行(蓋棺定論
  • 環(huán)繞通知:使用try…catch…finally結(jié)構(gòu)圍繞整個(gè)被代理的目標(biāo)方法,包括上面四種通知對(duì)應(yīng)的所有位置
    spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程
③切面

封裝通知方法的類。
spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

④目標(biāo)

被代理的目標(biāo)對(duì)象。

⑤代理

向目標(biāo)對(duì)象應(yīng)用通知之后創(chuàng)建的代理對(duì)象。

⑥連接點(diǎn)

這也是一個(gè)純邏輯概念,不是語法定義的。

把方法排成一排,每一個(gè)橫切位置看成x軸方向,把方法從上到下執(zhí)行的順序看成y軸,x軸和y軸的交叉點(diǎn)就是連接點(diǎn)。通俗說,就是spring允許你使用通知的地方
spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

⑦切入點(diǎn)

定位連接點(diǎn)的方式。

每個(gè)類的方法中都包含多個(gè)連接點(diǎn),所以連接點(diǎn)是類中客觀存在的事物(從邏輯上來說)。

如果把連接點(diǎn)看作數(shù)據(jù)庫中的記錄,那么切入點(diǎn)就是查詢記錄的 SQL 語句。

Spring 的 AOP 技術(shù)可以通過切入點(diǎn)定位到特定的連接點(diǎn)。通俗說,要實(shí)際去增強(qiáng)的方法

切點(diǎn)通過 org.springframework.aop.Pointcut 接口進(jìn)行描述,它使用類和方法作為連接點(diǎn)的查詢條件。

3.3、作用
  • 簡(jiǎn)化代碼:把方法中固定位置的重復(fù)的代碼抽取出來,讓被抽取的方法更專注于自己的核心功能,提高內(nèi)聚性。

  • 代碼增強(qiáng):把特定的功能封裝到切面類中,看哪里有需要,就往上套,被套用了切面邏輯的方法就被切面給增強(qiáng)了。

4、基于注解的AOP

4.1、技術(shù)說明

spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程
spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

  • 動(dòng)態(tài)代理分為JDK動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理
  • 當(dāng)目標(biāo)類有接口的情況使用JDK動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理,沒有接口時(shí)只能使用cglib動(dòng)態(tài)代理
  • JDK動(dòng)態(tài)代理動(dòng)態(tài)生成的代理類會(huì)在com.sun.proxy包下,類名為$proxy1,和目標(biāo)類實(shí)現(xiàn)相同的接口
  • cglib動(dòng)態(tài)代理動(dòng)態(tài)生成的代理類會(huì)和目標(biāo)在在相同的包下,會(huì)繼承目標(biāo)類
  • 動(dòng)態(tài)代理(InvocationHandler):JDK原生的實(shí)現(xiàn)方式,需要被代理的目標(biāo)類必須實(shí)現(xiàn)接口。因?yàn)檫@個(gè)技術(shù)要求代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)同樣的接口(兄弟兩個(gè)拜把子模式)。
  • cglib:通過繼承被代理的目標(biāo)類(認(rèn)干爹模式)實(shí)現(xiàn)代理,所以不需要目標(biāo)類實(shí)現(xiàn)接口。
  • AspectJ:是AOP思想的一種實(shí)現(xiàn)。本質(zhì)上是靜態(tài)代理,將代理邏輯“織入”被代理的目標(biāo)類編譯得到的字節(jié)碼文件,所以最終效果是動(dòng)態(tài)的。weaver就是織入器。Spring只是借用了AspectJ中的注解。
4.2、準(zhǔn)備工作

①添加依賴

在IOC所需依賴基礎(chǔ)上再加入下面依賴即可:

<dependencies>
    <!--spring context依賴-->
    <!--當(dāng)你引入Spring Context依賴之后,表示將Spring的基礎(chǔ)依賴引入了-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.2</version>
    </dependency>

    <!--spring aop依賴-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>6.0.2</version>
    </dependency>
    <!--spring aspects依賴-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>6.0.2</version>
    </dependency>

    <!--junit5測(cè)試-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.1</version>
    </dependency>

    <!--log4j2的依賴-->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.19.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j2-impl</artifactId>
        <version>2.19.0</version>
    </dependency>
</dependencies>

②準(zhǔn)備被代理的目標(biāo)資源

接口:

public interface Calculator {
    
    int add(int i, int j);
    
    int sub(int i, int j);
    
    int mul(int i, int j);
    
    int div(int i, int j);
    
}

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

@Component
public class CalculatorImpl implements Calculator {
    
    @Override
    public int add(int i, int j) {
    
        int result = i + j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
    
    @Override
    public int sub(int i, int j) {
    
        int result = i - j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
    
    @Override
    public int mul(int i, int j) {
    
        int result = i * j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
    
    @Override
    public int div(int i, int j) {
    
        int result = i / j;
    
        System.out.println("方法內(nèi)部 result = " + result);
    
        return result;
    }
}
4.3、創(chuàng)建切面類并配置
// @Aspect表示這個(gè)類是一個(gè)切面類
@Aspect
// @Component注解保證這個(gè)切面類能夠放入IOC容器
@Component
public class LogAspect {
    
    @Before("execution(public int com.atguigu.aop.annotation.CalculatorImpl.*(..))")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println("Logger-->前置通知,方法名:"+methodName+",參數(shù):"+args);
    }

    @After("execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Logger-->后置通知,方法名:"+methodName);
    }

    @AfterReturning(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", returning = "result")
    public void afterReturningMethod(JoinPoint joinPoint, Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Logger-->返回通知,方法名:"+methodName+",結(jié)果:"+result);
    }

    @AfterThrowing(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", throwing = "ex")
    public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Logger-->異常通知,方法名:"+methodName+",異常:"+ex);
    }
    
    @Around("execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        Object result = null;
        try {
            System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法執(zhí)行之前");
            //目標(biāo)對(duì)象(連接點(diǎn))方法的執(zhí)行
            result = joinPoint.proceed();
            System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法返回值之后");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法出現(xiàn)異常時(shí)");
        } finally {
            System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法執(zhí)行完畢");
        }
        return result;
    }
    
}

在Spring的配置文件中配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--
        基于注解的AOP的實(shí)現(xiàn):
        1、將目標(biāo)對(duì)象和切面交給IOC容器管理(注解+掃描)
        2、開啟AspectJ的自動(dòng)代理,為目標(biāo)對(duì)象自動(dòng)生成代理
        3、將切面類通過注解@Aspect標(biāo)識(shí)
    -->
    <context:component-scan base-package="com.atguigu.aop.annotation"></context:component-scan>

    <aop:aspectj-autoproxy />
</beans>

執(zhí)行測(cè)試:

public class CalculatorTest {

    private Logger logger = LoggerFactory.getLogger(CalculatorTest.class);

    @Test
    public void testAdd(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        Calculator calculator = ac.getBean( Calculator.class);
        int add = calculator.add(1, 1);
        logger.info("執(zhí)行成功:"+add);
    }

}

執(zhí)行結(jié)果:
spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

4.4、各種通知
  • 前置通知:使用@Before注解標(biāo)識(shí),在被代理的目標(biāo)方法執(zhí)行
  • 返回通知:使用@AfterReturning注解標(biāo)識(shí),在被代理的目標(biāo)方法成功結(jié)束后執(zhí)行(壽終正寢
  • 異常通知:使用@AfterThrowing注解標(biāo)識(shí),在被代理的目標(biāo)方法異常結(jié)束后執(zhí)行(死于非命
  • 后置通知:使用@After注解標(biāo)識(shí),在被代理的目標(biāo)方法最終結(jié)束后執(zhí)行(蓋棺定論
  • 環(huán)繞通知:使用@Around注解標(biāo)識(shí),使用try…catch…finally結(jié)構(gòu)圍繞整個(gè)被代理的目標(biāo)方法,包括上面四種通知對(duì)應(yīng)的所有位置

各種通知的執(zhí)行順序:

  • Spring版本5.3.x以前:
    • 前置通知
    • 目標(biāo)操作
    • 后置通知
    • 返回通知或異常通知
  • Spring版本5.3.x以后:
    • 前置通知
    • 目標(biāo)操作
    • 返回通知或異常通知
    • 后置通知
4.5、切入點(diǎn)表達(dá)式語法

①作用
spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程
②語法細(xì)節(jié)

  • 用*號(hào)代替“權(quán)限修飾符”和“返回值”部分表示“權(quán)限修飾符”和“返回值”不限

  • 在包名的部分,一個(gè)“*”號(hào)只能代表包的層次結(jié)構(gòu)中的一層,表示這一層是任意的。

    • 例如:*.Hello匹配com.Hello,不匹配com.atguigu.Hello
  • 在包名的部分,使用“*…”表示包名任意、包的層次深度任意

  • 在類名的部分,類名部分整體用*號(hào)代替,表示類名任意

  • 在類名的部分,可以使用*號(hào)代替類名的一部分

    • 例如:*Service匹配所有名稱以Service結(jié)尾的類或接口
  • 在方法名部分,可以使用*號(hào)表示方法名任意

  • 在方法名部分,可以使用*號(hào)代替方法名的一部分

    • 例如:*Operation匹配所有方法名以O(shè)peration結(jié)尾的方法
  • 在方法參數(shù)列表部分,使用(…)表示參數(shù)列表任意

  • 在方法參數(shù)列表部分,使用(int,…)表示參數(shù)列表以一個(gè)int類型的參數(shù)開頭

  • 在方法參數(shù)列表部分,基本數(shù)據(jù)類型和對(duì)應(yīng)的包裝類型是不一樣的

    • 切入點(diǎn)表達(dá)式中使用 int 和實(shí)際方法中 Integer 是不匹配的
  • 在方法返回值部分,如果想要明確指定一個(gè)返回值類型,那么必須同時(shí)寫明權(quán)限修飾符

    • 例如:execution(public int Service.(…, int)) 正確
      例如:execution(
      int *…Service.(…, int)) 錯(cuò)誤

spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

4.6、重用切入點(diǎn)表達(dá)式

①聲明

@Pointcut("execution(* com.atguigu.aop.annotation.*.*(..))")
public void pointCut(){}

②在同一個(gè)切面中使用

@Before("pointCut()")
public void beforeMethod(JoinPoint joinPoint){
    String methodName = joinPoint.getSignature().getName();
    String args = Arrays.toString(joinPoint.getArgs());
    System.out.println("Logger-->前置通知,方法名:"+methodName+",參數(shù):"+args);
}

③在不同切面中使用

@Before("com.atguigu.aop.CommonPointCut.pointCut()")
public void beforeMethod(JoinPoint joinPoint){
    String methodName = joinPoint.getSignature().getName();
    String args = Arrays.toString(joinPoint.getArgs());
    System.out.println("Logger-->前置通知,方法名:"+methodName+",參數(shù):"+args);
}
4.7、獲取通知的相關(guān)信息

①獲取連接點(diǎn)信息

獲取連接點(diǎn)信息可以在通知方法的參數(shù)位置設(shè)置JoinPoint類型的形參

@Before("execution(public int com.atguigu.aop.annotation.CalculatorImpl.*(..))")
public void beforeMethod(JoinPoint joinPoint){
    //獲取連接點(diǎn)的簽名信息
    String methodName = joinPoint.getSignature().getName();
    //獲取目標(biāo)方法到的實(shí)參信息
    String args = Arrays.toString(joinPoint.getArgs());
    System.out.println("Logger-->前置通知,方法名:"+methodName+",參數(shù):"+args);
}

②獲取目標(biāo)方法的返回值

@AfterReturning中的屬性returning,用來將通知方法的某個(gè)形參,接收目標(biāo)方法的返回值

@AfterReturning(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", returning = "result")
public void afterReturningMethod(JoinPoint joinPoint, Object result){
    String methodName = joinPoint.getSignature().getName();
    System.out.println("Logger-->返回通知,方法名:"+methodName+",結(jié)果:"+result);
}

③獲取目標(biāo)方法的異常

@AfterThrowing中的屬性throwing,用來將通知方法的某個(gè)形參,接收目標(biāo)方法的異常

@AfterThrowing(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
    String methodName = joinPoint.getSignature().getName();
    System.out.println("Logger-->異常通知,方法名:"+methodName+",異常:"+ex);
}
4.8、環(huán)繞通知
@Around("execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))")
public Object aroundMethod(ProceedingJoinPoint joinPoint){
    String methodName = joinPoint.getSignature().getName();
    String args = Arrays.toString(joinPoint.getArgs());
    Object result = null;
    try {
        System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法執(zhí)行之前");
        //目標(biāo)方法的執(zhí)行,目標(biāo)方法的返回值一定要返回給外界調(diào)用者
        result = joinPoint.proceed();
        System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法返回值之后");
    } catch (Throwable throwable) {
        throwable.printStackTrace();
        System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法出現(xiàn)異常時(shí)");
    } finally {
        System.out.println("環(huán)繞通知-->目標(biāo)對(duì)象方法執(zhí)行完畢");
    }
    return result;
}
4.9、切面的優(yōu)先級(jí)

相同目標(biāo)方法上同時(shí)存在多個(gè)切面時(shí),切面的優(yōu)先級(jí)控制切面的內(nèi)外嵌套順序。

  • 優(yōu)先級(jí)高的切面:外面
  • 優(yōu)先級(jí)低的切面:里面

使用@Order注解可以控制切面的優(yōu)先級(jí):

  • @Order(較小的數(shù)):優(yōu)先級(jí)高
  • @Order(較大的數(shù)):優(yōu)先級(jí)低

spring6-AOP面向切面編程,spring,java,后端,spring,aop,面向切面編程

5、基于XML的AOP

5.1、準(zhǔn)備工作

參考基于注解的AOP環(huán)境文章來源地址http://www.zghlxwxcb.cn/news/detail-714191.html

5.2、實(shí)現(xiàn)
<context:component-scan base-package="com.atguigu.aop.xml"></context:component-scan>

<aop:config>
    <!--配置切面類-->
    <aop:aspect ref="loggerAspect">
        <aop:pointcut id="pointCut" 
                   expression="execution(* com.atguigu.aop.xml.CalculatorImpl.*(..))"/>
        <aop:before method="beforeMethod" pointcut-ref="pointCut"></aop:before>
        <aop:after method="afterMethod" pointcut-ref="pointCut"></aop:after>
        <aop:after-returning method="afterReturningMethod" returning="result" pointcut-ref="pointCut"></aop:after-returning>
        <aop:after-throwing method="afterThrowingMethod" throwing="ex" pointcut-ref="pointCut"></aop:after-throwing>
        <aop:around method="aroundMethod" pointcut-ref="pointCut"></aop:around>
    </aop:aspect>
</aop:config>

到了這里,關(guān)于spring6-AOP面向切面編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Spring面向切面編程(AOP)

    Spring面向切面編程(AOP)

    AOP(Aspect Oriented Programming),即面向切面編程,利用一種稱為\\\"橫切\(zhòng)\\"的技術(shù),剖開封裝的對(duì)象內(nèi)部,并將那些影響了多個(gè)類的公共行為封裝到一個(gè)可重用模塊,并將其命名為\\\"Aspect\\\",即切面。所謂\\\"切面\\\",簡(jiǎn)單說就是那些與業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任封裝

    2024年02月07日
    瀏覽(31)
  • [SSM]Spring面向切面編程AOP

    [SSM]Spring面向切面編程AOP

    目錄 十五、面向切面編程AOP 15.1AOP介紹 15.2AOP的七大術(shù)語 15.3切點(diǎn)表達(dá)式 15.4使用Spring的AOP 15.4.1準(zhǔn)備工作 15.4.2基于AspectJ的AOP注解式開發(fā) 15.4.3基于XML配置方式的AOP(了解) 15.5AOP的實(shí)際案例:事務(wù)處理 15.6AOP的實(shí)際案例:安全日志 IoC使軟件組件松耦合。AOP讓你能夠捕捉系統(tǒng)中經(jīng)

    2024年02月15日
    瀏覽(28)
  • Spring AOP(面向切面編程)和方法攔截

    Spring AOP(面向切面編程)和方法攔截 Spring是一款廣泛使用的Java開發(fā)框架,提供了豐富的功能和工具,用于簡(jiǎn)化企業(yè)級(jí)應(yīng)用程序的開發(fā)。其中一個(gè)重要的特性是面向切面編程(AOP)和方法攔截。本文將介紹Spring AOP和方法攔截的概念、工作原理以及在實(shí)際開發(fā)中的應(yīng)用。 在軟

    2024年02月05日
    瀏覽(24)
  • 認(rèn)識(shí) spring AOP (面向切面編程) - springboot

    認(rèn)識(shí) spring AOP (面向切面編程) - springboot

    本篇介紹什么是spring AOP, AOP的優(yōu)點(diǎn),使用場(chǎng)景,spring AOP的組成,簡(jiǎn)單實(shí)現(xiàn)AOP 并 了解它的通知;如有錯(cuò)誤,請(qǐng)?jiān)谠u(píng)論區(qū)指正,讓我們一起交流,共同進(jìn)步! 本文開始 AOP: 面向切面編程,也就是面向某一類編程,對(duì)某一類事情進(jìn)行統(tǒng)一處理; spring AOP: 是實(shí)現(xiàn)了AOP這種思想的一

    2024年02月14日
    瀏覽(29)
  • 切面的魔力:解密Spring AOP 面向切面編程

    切面的魔力:解密Spring AOP 面向切面編程

    目錄 一、AOP簡(jiǎn)介 1.1 什么是AOP ? 1.2?什么是面向切面編程 ? 1.3?AOP 的特點(diǎn) 二、?AOP的基本概念解讀 2.1 AOP的基本概念 2.2 AOP 概念趣事解讀 三、代碼情景演示 3.1?編寫目標(biāo)對(duì)象(超級(jí)英雄們正常的行動(dòng)) 3.2 編寫通知類 3.2.1?前置通知 3.2.2 后置通知 3.2.3 異常通知 3.2.4 環(huán)繞通知

    2024年02月11日
    瀏覽(89)
  • 【Spring AOP】結(jié)合日志面向切面編程 兩種寫法

    ??????? 這里需要提前了解什么是Spring的AOP(Aspect Oriented Programming)。是在OOP(面向?qū)ο螅┧枷氲囊环N拓展思想。 簡(jiǎn)單來說就是將某個(gè)代碼塊嵌入到其它的代碼塊中 。筆者先前學(xué)Spring也有學(xué)什么IoC啊AOP啊,但實(shí)際上沒有用過、就那聽過學(xué)過沒啥用的。。沒會(huì)兒就忘記了。

    2024年02月13日
    瀏覽(28)
  • JAVA:面向切面編程AOP

    ? ? ? ? 把某一些功能提取出來與某一對(duì)象進(jìn)行隔離,提取之后可以對(duì)某哥單方面的功能進(jìn)行修改和擴(kuò)展 ? ? ? ? 也就是把眾多方法中的的所有公共代碼抽取出來,放到某個(gè)地方集中管理 ????????對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行了隔離,從而降低業(yè)務(wù)邏輯各部分之間的耦合,

    2024年02月07日
    瀏覽(17)
  • Spring AOP (面向切面編程)原理與代理模式—實(shí)例演示

    Spring AOP (面向切面編程)原理與代理模式—實(shí)例演示

    Spring 中文文檔 (springdoc.cn) Spring | Home 官網(wǎng) ????????Java是一個(gè)面向?qū)ο螅∣OP)的語言,但它有一些弊端。雖然使用OOP可以通過組合或繼承的方式來實(shí)現(xiàn)代碼的重用。但當(dāng)我們需要為多個(gè)不具有繼承關(guān)系的對(duì)象(一般指的是兩個(gè)不同的類,它們之間沒有繼承自同一個(gè)父類或接

    2024年02月15日
    瀏覽(28)
  • Spring AOP使用指南: 強(qiáng)大的面向切面編程技術(shù)

    Spring AOP使用指南: 強(qiáng)大的面向切面編程技術(shù)

    ???? 博主貓頭虎(????)帶您 Go to New World??? ?? 博客首頁 ——????貓頭虎的博客?? ?? 《面試題大全專欄》 ?? 文章圖文并茂??生動(dòng)形象??簡(jiǎn)單易學(xué)!歡迎大家來踩踩~?? ?? 《IDEA開發(fā)秘籍專欄》 ?? 學(xué)會(huì)IDEA常用操作,工作效率翻倍~?? ?? 《100天精通Golang(基礎(chǔ)

    2024年02月09日
    瀏覽(26)
  • 【JavaEE】面向切面編程AOP是什么-Spring AOP框架的基本使用

    【JavaEE】面向切面編程AOP是什么-Spring AOP框架的基本使用

    【JavaEE】 AOP(1) 1.1 AOP 與 Spring AOP AOP ( A spect O riented P rogramming),是一種思想,即 面向切面編程 Spring AOP 則是一個(gè)框架,Spring項(xiàng)目中需要引入依賴而使用 AOP和Spring AOP的關(guān)系就相當(dāng)于IoC和DI Spring AOP讓開發(fā)者能夠半自動(dòng)的開發(fā)AOP思想下實(shí)現(xiàn)的功能 1.2 沒有AOP的世界是怎樣的

    2024年02月11日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包