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

SpringBoot中的Aop用法示例詳解

 更新時(shí)間:2022年12月22日 09:15:17   作者:這很張揚(yáng)  
這篇文章主要介紹了SpringBoot中的Aop用法,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

什么是Aop

主要介紹springboot中aop的使用,用過Spring框架的都知道,aop是spring框架的兩大核心功能之一,還有一個(gè)就是ioc,下面我們就springboot中如何引入aop來做一下探討

  • 引入AOP依賴包后,一般來說并不需要去做其他配置,使用過Spring注解配置方式的人會(huì)問是否需要在程序主類中增加@EnableAspectJAutoProxy來啟用,實(shí)際并不需要。
  • 因?yàn)樵贏OP的默認(rèn)配置屬性中,spring.aop.auto屬性默認(rèn)是開啟的,也就是說只要引入了AOP依賴后,默認(rèn)已經(jīng)增加了@EnableAspectJAutoProxy
  • Springboot中有關(guān)AOP相關(guān)的自動(dòng)配置包為:AopAutoConfiguration

因?yàn)樵贏OP的默認(rèn)配置屬性中,spring.aop.auto屬性默認(rèn)是開啟的,也就是說只要引入了AOP依賴后,默認(rèn)已經(jīng)增加了@EnableAspectJAutoProxy

Springboot中有關(guān)AOP相關(guān)的自動(dòng)配置包為:AopAutoConfiguration

Aop概述

相關(guān)注解

  • @Component :將當(dāng)前類注入到Spring容器內(nèi)
  • @Aspect :表明是一個(gè)切面類
  • @Before :前置通知,在方法執(zhí)行之前執(zhí)行
  • @After :后置通知,在方法執(zhí)行之后執(zhí)行
  • @AfterRuturning :返回通知,在方法返回結(jié)果之后執(zhí)行
  • @AfterThrowing :異常通知,在方法拋出異常之后執(zhí)行
  • @Around :環(huán)繞通知,圍繞著方法執(zhí)行
  • @Pointcut :切入點(diǎn),PointCut(切入點(diǎn))表達(dá)式有很多種,其中execution用于使用切面的連接點(diǎn)。

上面所提到的五種通知方法中,除了環(huán)繞通知外,其他的四個(gè)通知注解中,加或者不加參數(shù)JoinPoint都可以,如果有用到JoinPoint的地方就加,用不到就可以不加。

JoinPoint:里包含了類名、被切面的方法名,參數(shù)等屬性。

環(huán)繞通知:參數(shù)必須為ProceedingJoinPoint,pjp.proceed相應(yīng)于執(zhí)行被切面的方法。

返回通知:可以加returning = “XXX”,XXX即為被切入方法的返回值,本例中是controller類中方法的返回值。

異常通知:可以加throwing = “XXX”,供讀取異常信息。

返回通知異常通知只會(huì)執(zhí)行一個(gè),如果產(chǎn)生異常,返回通知就不執(zhí)行,后置通知一定會(huì)執(zhí)行

== 環(huán)繞通知一般單獨(dú)使用,環(huán)繞通知可以替代上面的四種通知,后面單獨(dú)介紹。==

相關(guān)概念

  • Joinpoint(連接點(diǎn)):所謂連接點(diǎn)是指那些被攔截到的點(diǎn),在 spring 中,這些點(diǎn)指的是方法,因?yàn)?spring 只支持方法類型的連接點(diǎn),通俗的說就是被增強(qiáng)類中的所有方法
  • PointCut(切入點(diǎn)):所謂切入點(diǎn)是指我們要對哪些 Joinpoint 進(jìn)行攔截的定義,通俗的說就是被增強(qiáng)類中的被增強(qiáng)的方法,因?yàn)楸辉鰪?qiáng)類中并不是所有的方法都被代理了
  • Advice(通知/增強(qiáng)):所謂通知是指攔截到 Joinpoint (被增強(qiáng)的方法)之后所要做的事情就是通知,通俗的說就是對被增強(qiáng)的方法進(jìn)行增強(qiáng)的代碼
  • 通知的類型:前置通知,返回通知,異常通知,后置通知,環(huán)繞通知
  • 前置通知:在被代理方法執(zhí)行之前執(zhí)行
  • 返回通知:在被代理方法執(zhí)行之后執(zhí)行
  • 異常通知:在被代理方法執(zhí)行出錯(cuò)的時(shí)候執(zhí)行
  • 后置通知:無論怎樣都會(huì)執(zhí)行
  • Aspect(切面):是切入點(diǎn)和通知(引介)的結(jié)合,通俗的說就是建立切入點(diǎn)和通知方法在創(chuàng)建時(shí)的對應(yīng)關(guān)系

注意:返回通知和異常通知只能有一個(gè)會(huì)被執(zhí)行,因?yàn)榘l(fā)生異常執(zhí)行異常通知,然后就不會(huì)繼續(xù)向下執(zhí)行,自然后置通知也就不會(huì)被執(zhí)行,反之亦然。

實(shí)例1

使用aop來完成全局請求日志處理。

在這里插入圖片描述

第一步:使用Spring Initializr快速創(chuàng)建一個(gè)springboot web項(xiàng)目,名稱為testaop
第二步:引入aop相關(guān)的依賴

<!--aop相關(guān)的依賴引入-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

第三步:創(chuàng)建個(gè)controller

@RestController
public class HelloController {
    @RequestMapping("/helloAop")
    public Object hello(){
        return "hello aop";
    }
    @RequestMapping("/helloError")
    public Object helloError(){
        return 1/0;
    }
}

第四步:創(chuàng)建一個(gè)aspect切面類

@Aspect
@Component
public class MyAop {
    //切入點(diǎn):待增強(qiáng)的方法
    @Pointcut("execution(public * com.aismall.testaop.controller.*.*(..))")
    //切入點(diǎn)簽名
    public void log(){
        System.out.println("pointCut簽名。。。");
    }
    //前置通知
    @Before("log()")
    public void deBefore(JoinPoint jp) throws Throwable {
        // 接收到請求,記錄請求內(nèi)容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 記錄下請求內(nèi)容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("CLASS_METHOD : " + jp);
        System.out.println("ARGS : " + Arrays.toString(jp.getArgs()));

    }
    //返回通知
    @AfterReturning(returning = "ret", pointcut = "log()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內(nèi)容
        System.out.println("返回通知:方法的返回值 : " + ret);
    }

    //異常通知
    @AfterThrowing(throwing = "ex", pointcut = "log()")
    public void throwss(JoinPoint jp,Exception ex){
        System.out.println("異常通知:方法異常時(shí)執(zhí)行.....");
        System.out.println("產(chǎn)生異常的方法:"+jp);
        System.out.println("異常種類:"+ex);
    }

    //后置通知
    @After("log()")
    public void after(JoinPoint jp){
        System.out.println("后置通知:最后且一定執(zhí)行.....");
    }
}

第六步:啟動(dòng)項(xiàng)目

  • 請求鏈接:http://localhost:8080/helloAop
  • 控制臺返回的結(jié)果:
URL : http://localhost:8080/helloAop
HTTP_METHOD : GET
CLASS_METHOD : execution(Object com.aismall.testaop.controller.HelloController.hello())
ARGS : []
返回通知:方法的返回值 : hello aop
后置通知:最后且一定執(zhí)行.....
  • 請求鏈接:http://localhost:8080/helloError
  • 控制臺返回的結(jié)果(部分):
URL : http://localhost:8080/helloError
HTTP_METHOD : GET
CLASS_METHOD : execution(Object com.aismall.testaop.controller.HelloController.helloError())
ARGS : []
異常通知:方法異常時(shí)執(zhí)行.....
產(chǎn)生異常的方法execution(Object com.aismall.testaop.controller.HelloController.helloError())
異常種類java.lang.ArithmeticException: / by zero
后置通知:最后且一定執(zhí)行.....

分析:返回通知和異常通知只會(huì)執(zhí)行一個(gè),后置通知一定會(huì)執(zhí)行。

@PointCut 表達(dá)式詳解

  • PointCut:切入點(diǎn),指哪些方法需要被執(zhí)行AOP,PointCut表達(dá)式可以有一下幾種方式 execution

execution(表達(dá)式)

  • 表達(dá)式:訪問修飾符 返回值 包名.包名.包名…類名.方法名(參數(shù)列表)
  • 標(biāo)準(zhǔn)的表達(dá)式寫法范例:
public void com.aismall.testaop.controller.HelloController.helloAop()

訪問修飾符可以省略

void com.aismall.testaop.controller.HelloController.helloAop()

返回值可以使用通配符*,表示任意返回值

* com.aismall.testaop.controller.HelloController.helloAop()

包名可以使用通配符,表示任意包,但是有幾級包,就需要寫幾個(gè)*.

* *.*.*.*.HelloController.helloAop()

包名可以使用…表示當(dāng)前包及其子包

* *...HelloController.helloAop()

類名和方法名都可以使用*來實(shí)現(xiàn)通配

* *..*.*()
  • 參數(shù)列表:
  • 可以直接寫數(shù)據(jù)類型:
  • 基本類型直接寫名稱 :例如,int
  • 引用類型寫包名.類名的方式 :例如,java.lang.String
  • 可以使用通配符*表示任意類型,但是必須有參數(shù)
  • 可以使用…表示有無參數(shù)均可,有參數(shù)可以是任意類型

全通配寫法:* ….*(…)

within

within(表達(dá)式):是用來指定類型的,指定類型中的所有方法將被攔截

  • 表達(dá)式:包名.包名.包名…類名
  • 標(biāo)準(zhǔn)的表達(dá)式寫法范例:
com.aismall.testaop.controller.HelloController

舉例:匹配HelloController類對應(yīng)對象的所有方法,并且只能是HelloController的對象,不能是它的子對象。

within(com.aismall.testaop.controller.HelloController)

也可以使用通配符 * :匹配com.aismall包及其子包下面的所有類的所有方法。

within(com.aismall…*)

this

  • SpringAOP是基于代理的,this就代表代理對象,語法是this(type),當(dāng)生成的代理對象可以轉(zhuǎn)化為type指定的類型時(shí)表示匹配。
  • this(com.aismall.testaop.controller.HelloController) 匹配生成的代理對象是HelloController類型的所有方法的外部調(diào)用

target

  • SpringAOP是基于代理的,target表示被代理的目標(biāo)對象,當(dāng)被代理的目標(biāo)對象可以轉(zhuǎn)換為指定的類型時(shí)則表示匹配。
  • target(com.aismall.testaop.controller.HelloController) 匹配所有被代理的目標(biāo)對象能夠轉(zhuǎn)化成HelloController類型的所有方法的外部調(diào)用。

args:

args用來匹配方法參數(shù)

args() 匹配不帶參數(shù)的方法
args(java.lang.String) 匹配方法參數(shù)是String類型的
==args(…) == 帶任意參數(shù)的方法
args(java.lang.String,…) 匹配第一個(gè)參數(shù)是String類型的,其他參數(shù)任意。最后一個(gè)參數(shù)是String的同理

@annotation:

帶有相應(yīng)注解的方法,比如對標(biāo)有@Transactional注解的方法進(jìn)行增強(qiáng)

@annotation(org.springframework.transaction.annotation.Transactional)
  • @within和 @target針對類的注解
  • @annotation 針對方法的注解

@args:

參數(shù)帶有相應(yīng)標(biāo)注的任意方法,比如@Transactional

@args(org.springframework.transaction.annotation.Transactional)

邏輯運(yùn)算符

表達(dá)式可由多個(gè)切點(diǎn)函數(shù)通過邏輯運(yùn)算組成

  • 基本使用:使用log()方法相當(dāng)于直接使用上面的表達(dá)式
//PointCut表達(dá)式
@Pointcut("execution(public * com.aismall.testaop.controller.HelloController.*(..))")
//PointCut簽名
public void log(){
}

PointCut中的運(yùn)算符:PointCut中可以使用 && 、|| 、! 運(yùn)算

@Pointcut("execution(public * com.aismall.testaop.controller.HelloController.*(..))")
public void cutController(){
}

@Pointcut("execution(public * com.aismall.testaop.service.UserService.*(..))")
public void cutService(){
}

//使用 && 運(yùn)算符,則cutAll()的作用等同于cutController 和 cutService 之和
@Pointcut("cutController() && cutService()")
public void cutAll(){
}

實(shí)例2

@annotation方式

在這里插入圖片描述

第一步:編寫一個(gè)自定義注解

//表示次注解可以標(biāo)注在類和方法上
@Target({ElementType.METHOD, ElementType.TYPE})
//運(yùn)行時(shí)生效
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLogAnnotation {
    //定義一個(gè)變量,可以接受參數(shù)
    String desc() default " ";
}

第二步:在HelloController類中添加一個(gè)方法

@RequestMapping("helloAnnotation")
//標(biāo)有這個(gè)注解的方法會(huì)被增強(qiáng)
@MyLogAnnotation(desc = "@Annotation")
public Object helloAnnotation() {
    return "hello annotation";
}

第三步:切面類

@Aspect
@Component
public class MyAopAnnotation {
    //切入點(diǎn):增強(qiáng)標(biāo)有MyLogAnnotation注解的方法
    @Pointcut(value="@annotation(com.aismall.testaop.MyAnnotation.MyLogAnnotation)")
    //切入點(diǎn)簽名
    public void logAnnotation(){
        System.out.println("pointCut簽名。。。");
    }
    //前置通知
    @Before("logAnnotation()")
    public void deBefore(JoinPoint jp) throws Throwable {
        // 接收到請求,記錄請求內(nèi)容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 記錄下請求內(nèi)容
        System.out.println("URL : " + request.getRequestURL().toString());
    }
    //返回通知
    @AfterReturning(returning = "ret", pointcut = "logAnnotation()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內(nèi)容
        System.out.println("返回通知:方法的返回值 : " + ret);
    }

    //異常通知
    @AfterThrowing(throwing = "ex", pointcut = "logAnnotation()")
    public void throwss(JoinPoint jp,Exception ex){
        System.out.println("異常通知:方法異常時(shí)執(zhí)行.....");
        System.out.println("產(chǎn)生異常的方法:"+jp);
        System.out.println("異常種類:"+ex);
    }

    //后置通知
    @After("logAnnotation()")
    public void after(JoinPoint jp){
        System.out.println("后置通知:最后且一定執(zhí)行.....");
    }
}

第四步:啟動(dòng)項(xiàng)目

  • 請求鏈接:http://localhost:8080/helloAnnotation
  • 控制臺返回的結(jié)果:

URL : http://localhost:8080/helloAnnotation

返回通知:方法的返回值 : hello annotation

后置通知:最后且一定執(zhí)行.....

環(huán)繞通知

spring的通知(Advice)中 一共有五種通知,之前已經(jīng)介紹了四種,為什么不把環(huán)繞通知和它們放在一起說,因?yàn)榄h(huán)繞通知可以把前面的四種通知都表示出來,而且環(huán)繞通知一般單獨(dú)使用

環(huán)繞通知的使用:

  • Spring框架為我們提供了一個(gè)接口:ProceedingJoinPoint,該接口有一個(gè)方法proceed(),此方法就相當(dāng)于明確調(diào)用切入點(diǎn)方法。
  • 該接口作為環(huán)繞通知的方法參數(shù),在程序執(zhí)行時(shí),spring框架會(huì)為我們提供該接口的實(shí)現(xiàn)類供我們使用。
  • 增強(qiáng)代碼寫在調(diào)用proceed()方法之前為前置通知,之后為返回通知,寫在catch中為異常通知,寫在finally中為后置通知

在這里插入圖片描述

第一步:在HelloController類中添加一個(gè)方法

@RequestMapping("/helloAround")
public Object helloAround(){
    System.out.println("helloAround執(zhí)行了。。。");
    return "hello around";
}

第二步:切面類

@Aspect
@Component
public class MyAroundAop {
    //切入點(diǎn):待增強(qiáng)的方法
    @Pointcut("execution(public * com.aismall.testaop.controller.*.*(..))")
    //切入點(diǎn)簽名
    public void logAround() {
        System.out.println("pointCut簽名。。。");
    }

    //環(huán)繞通知,環(huán)繞增強(qiáng),相當(dāng)于MethodInterceptor
    @Around("logAround()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) {
        Object rtValue = null;
        try {
            Object[] args = pjp.getArgs();//得到方法執(zhí)行所需的參數(shù)

            System.out.println("通知類中的aroundAdvice方法執(zhí)行了。。前置");

            rtValue = pjp.proceed(args);//明確調(diào)用切入點(diǎn)方法(切入點(diǎn)方法)

            System.out.println("通知類中的aroundAdvice方法執(zhí)行了。。返回");
            System.out.println("返回通知:"+rtValue);

            return rtValue;
        } catch (Throwable e) {
            System.out.println("通知類中的aroundAdvice方法執(zhí)行了。。異常");
            throw new RuntimeException(e);
        } finally {
            System.out.println("通知類中的aroundAdvice方法執(zhí)行了。。后置");
        }
    }
}

第三步:啟動(dòng)項(xiàng)目

  • 請求鏈接:http://localhost:8080/helloAround
  • 控制臺返回的結(jié)果:

通知類中的aroundAdvice方法執(zhí)行了。。前置
helloAround執(zhí)行了。。。
通知類中的aroundAdvice方法執(zhí)行了。。返回
返回通知:hello around
通知類中的aroundAdvice方法執(zhí)行了。。后置

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

相關(guān)文章

  • springboot 錯(cuò)誤處理小結(jié)

    springboot 錯(cuò)誤處理小結(jié)

    在 java web開發(fā)過程中,難免會(huì)有一些系統(tǒng)異?;蛉藶楫a(chǎn)生一些異常。在 RESTful springboot 項(xiàng)目中如何優(yōu)雅的處理?下面腳本之家小編給大家?guī)砹藄pringboot 錯(cuò)誤處理小結(jié),感興趣的朋友一起看看吧
    2018-03-03
  • java中l(wèi)ambda表達(dá)式語法說明

    java中l(wèi)ambda表達(dá)式語法說明

    “Lambda 表達(dá)式”(lambda expression)是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名,直接對應(yīng)于其中的lambda抽象(lambda abstraction),是一個(gè)匿名函數(shù),即沒有函數(shù)名的函數(shù)。Lambda表達(dá)式可以表示閉包(注意和數(shù)學(xué)傳統(tǒng)意義上的不同)。
    2016-09-09
  • springboot增加注解緩存@Cacheable的實(shí)現(xiàn)

    springboot增加注解緩存@Cacheable的實(shí)現(xiàn)

    這篇文章主要介紹了springboot增加注解緩存@Cacheable的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java WebService 簡單實(shí)例(附實(shí)例代碼)

    Java WebService 簡單實(shí)例(附實(shí)例代碼)

    本篇文章主要介紹了Java WebService 簡單實(shí)例(附實(shí)例代碼), Web Service 是一種新的web應(yīng)用程序分支,他們是自包含、自描述、模塊化的應(yīng)用,可以發(fā)布、定位、通過web調(diào)用。有興趣的可以了解一下
    2017-01-01
  • 關(guān)于List、Map、Stream初始化方式

    關(guān)于List、Map、Stream初始化方式

    這篇文章主要介紹了關(guān)于List、Map、Stream初始化方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 詳解Spring boot/Spring 統(tǒng)一錯(cuò)誤處理方案的使用

    詳解Spring boot/Spring 統(tǒng)一錯(cuò)誤處理方案的使用

    這篇文章主要介紹了詳解Spring boot/Spring 統(tǒng)一錯(cuò)誤處理方案的使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • Java中Spring MVC接收表單數(shù)據(jù)的常用方法

    Java中Spring MVC接收表單數(shù)據(jù)的常用方法

    Spring MVC是Spring框架中的一個(gè)模塊,用于開發(fā)基于MVC(Model-View-Controller)架構(gòu)的Web應(yīng)用程序,它提供了一種輕量級的、靈活的方式來構(gòu)建Web應(yīng)用,同時(shí)提供了豐富的功能和特性,本文給大家介紹了Spring MVC接收表單數(shù)據(jù)的方法,需要的朋友可以參考下
    2024-05-05
  • Spring?Cache簡單介紹和使用大全

    Spring?Cache簡單介紹和使用大全

    Spring?Cache是一個(gè)框架,實(shí)現(xiàn)了基于注解的緩存功能,只需要簡單地加一個(gè)注解,就能實(shí)現(xiàn)緩存功能,這篇文章主要介紹了Spring?Cache簡介和使用,需要的朋友可以參考下
    2023-03-03
  • Java Socket一對多通信實(shí)現(xiàn)之并發(fā)處理方式

    Java Socket一對多通信實(shí)現(xiàn)之并發(fā)處理方式

    這篇文章主要介紹了Java Socket一對多通信實(shí)現(xiàn)之并發(fā)處理方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Mybatis-plus批量插入的2種方式總結(jié)

    Mybatis-plus批量插入的2種方式總結(jié)

    這篇文章主要給大家總結(jié)介紹了關(guān)于Mybatis-plus批量插入的2種方式,Mybatis-Plus提供了多種方式進(jìn)行批量插入優(yōu)化,文中通過代碼示例將實(shí)現(xiàn)的方法介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08

最新評論

琼中| 浠水县| 义乌市| 监利县| 安吉县| 荔浦县| 固阳县| 宁陵县| 长宁县| 平利县| 稷山县| 库伦旗| 万荣县| 将乐县| 徐州市| 婺源县| 泰州市| 双鸭山市| 田东县| 晴隆县| 翼城县| 乌拉特中旗| 浙江省| 读书| 吐鲁番市| 沧州市| 行唐县| 荔波县| 白河县| 景德镇市| 万宁市| 宁阳县| 馆陶县| 株洲市| 大同县| 呈贡县| 淮北市| 汽车| 湘潭县| 临泽县| 江城|