亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Spring AOP

 更新時間:2021年08月24日 14:26:22   作者:Acelin_H  
本文非常詳細講解了Spring AOP,本篇文章通過大量的代碼,講解了Spring AOP的使用,以下就是詳細內(nèi)容,需要的朋友可以參考下

什么是AOP?

​AOP,即我們平時經(jīng)常提到的面向切面編程。首先我們要理解一個叫橫切關(guān)注點(cross-cutting concern)的概念,它其實是描述我們應(yīng)用中的功能,假如有一個功能,它在應(yīng)用程序中很多個地方都用了,那么我們把這樣的功能稱之為橫切關(guān)注點。

​日常開發(fā)中,我們都會將不同的業(yè)務(wù)場景抽象出對應(yīng)的模塊進行開發(fā),而不同的模塊,除了那些針對特定領(lǐng)域的核心功能外,還有一些相同的輔助功能,比如日志管理、安全管理、事務(wù)管理等等。橫切關(guān)注點這個概念其實就點明了:類似這樣的功能就是我們面向切面編程需要關(guān)注的地方。這也是面向切面編程的意義所在:它幫助我們實現(xiàn)橫切關(guān)注點和他們所影響的對象之間的解耦。

​面向切面編程的實質(zhì),就是講橫切關(guān)注點模塊化成稱為切面的特殊的類。

AOP術(shù)語

以下討論都基于SpringAOP

通知(Advice)

切面的工作被稱為通知。也就是定義了切面的要做什么,以及何時做的問題。下面是Spring切面有5種類型的通知,以及相對應(yīng)的在SpringBoot中的五個注解

  • 前置通知(Before):方法調(diào)用之前,對應(yīng)@Before
  • 后置通知(After):方法調(diào)用之后(不關(guān)心方法輸出是什么)對應(yīng)@After
  • 返回通知(After-returning):目標方法成功執(zhí)行之后,對應(yīng)@AfterReturning
  • 異常通知(After-throwing):目標方法拋出異常之后,對應(yīng)@AfterThrowing
  • 環(huán)繞通知(Around):方法調(diào)用之前和之后,對應(yīng)@Around
  • 后置通知和返回通知的區(qū)別

后置通知應(yīng)用時機在返回通知之后,任何情況下都會應(yīng)用,而返回通知只有方法正常執(zhí)行

正常返回后執(zhí)行

  • 環(huán)繞通知與其它通知的區(qū)別

不同于其它的通知,環(huán)繞通知有目標方法的執(zhí)行權(quán),能夠控制目標方法是否執(zhí)行。而其它的通知更多是對目標方法的一個增強,無法影響目標方法的執(zhí)行

以上兩點,我們下面會通過一個例子更好的體會其中的差異。

連接點(Join point)

程序中那些我們想要應(yīng)用通知的地方,就是連接點。這個點可以是我們調(diào)用方法時、拋出異常時或甚至是修改某一個字段的時候。切面代碼(通知)可以通過這些點插入到應(yīng)用的正常流程中,是原本的功能增添新的行為。

切點(Pointcut)

我們的應(yīng)用程序可能會有很多個連接點需要我們應(yīng)用通知,所以我們有必要把連接點的分類匯總,抽象出相同的特點,好讓正確的切面切入到正確的地方去,各司其職,而不是切入所有的連接點。切點定義 了一個切面需要在哪里進行切入。是一堆具有特定切面切入需求的連接點的共性抽象。

我們通常通過明確類和方法名、或者匹配正則表達式的方式來指定切點

連接點和切點的區(qū)別

切點是對的擁有相同特點的連接點集合的一個抽象。切點定義了連接點的特性,是一個描述性的歸納,由于在SpringAOP中切點的切入級別是方法,所以那些符合切點定義的方法,都是一個連接點,連接點是切點的具象表現(xiàn)。

切面(Aspect)

切面是通知和切點的結(jié)合。通知和切點共同定了切面的全部內(nèi)容——它想要干什么,在何時何地完成功能。

引入(Introduction)

引入能夠讓我們在不修改原有類的代碼的基礎(chǔ)上,添加生的方法或?qū)傩浴?/p>

織入(Weaving)

織入是把切面應(yīng)用到目標對象并創(chuàng)建新的代理對象的過程。

SpringAOP

SpringAOP的特點

SpringAOP是通過動態(tài)代理實現(xiàn)的。不同于AspectJ等其他aop框架,SpringAOP只支持方法級別的切點,不支持類構(gòu)造器或字段級別的切點。因此只能攔截方法進行通知,而在對象創(chuàng)建或?qū)ο笞兞康男薷臅r,都無法應(yīng)用通知

SpringBoot集成SpringAOP

SpringBoot引入AOP依賴后,spring.aop.auto屬性默認是開啟的,也就是說只要引入了AOP依賴后,默認已經(jīng)增加了@EnableAspectJAutoProxy

現(xiàn)在我們來設(shè)想一個場景:我有若干個業(yè)務(wù)場景,每個場景對應(yīng)一個服務(wù),有些服務(wù)需要我在調(diào)服務(wù)的時候,打印開始和結(jié)束信息,并輸入服務(wù)處理的時長。

- 依賴引入

首先在項目中引入SpringAOP的依賴:

<!--引入AOP依賴-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

- 創(chuàng)建注解

創(chuàng)建一個自定義注解@ApiLog,用boolean類型的字段來決定是否開啟日志輸入功能,代碼如下:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLog {
    boolean isOn() default true;
}

- 定義切面

定義一個切面類MyAspect.java,代碼如下

@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* com.acelin.hello.study.springTest.aop.AspectController.*(..))")
    private void onePointcut(){}

    @Around("onePointcut()")
    public Object around(ProceedingJoinPoint point)throws Throwable{

        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        /* 獲取方法上的注解 */
        ApiLog apiLog = method.getAnnotation(ApiLog.class);
        if (apiLog != null && apiLog.isOn()){
            System.out.println("ApiLog is on!");
        }

        Object[] objects = point.getArgs();
        String bussinessName = (String) objects[0];
        System.out.println("-- " + bussinessName + " start --");
        long begin = System.currentTimeMillis();
        Object object = point.proceed();
        long end = System.currentTimeMillis();
        System.out.println("-- " + bussinessName + " end  耗時" + (end - begin) + "ms --");
        return object;
    }
}

- 設(shè)置切點

@Pointcut("execution(* com.acelin.hello.study.springTest.aop.AspectController.*(..))")
private void onePointcut(){}

@Pointcut注解表示聲明一個切點,然后我們要配置execution指示器,它用來匹配所有符合條件的連接點。已上面的指示器配置* com.acelin.hello.study.springTest.aop.AspectController.*(..)為例,分析一下指示器的寫法

  • 第一個*號:表示的不關(guān)心方法的返回值類型
  • 中間的com.acelin.hello.study.springTest.aop.AspectController.*指定方法的特點
  • 第二個*號:表示AspectController類下的任意方法
  • (..):表示不關(guān)心參數(shù)個數(shù)和類型

- 業(yè)務(wù)接口編寫

我們寫一個簡單的接口,然后注釋我們自定義的注解,開啟相關(guān)日志的輸出。

@RestController
@RequestMapping("/aop")
public class AspectController implements IAspect{

    @RequestMapping("/test/1/{businessName}")
    @ApiLog(isOn = true)
    public void testAop(@PathVariable("businessName") String businessName){
        System.out.println("This is a controller about aop test!");
    }
}

- 測試

測試結(jié)果如下:

ApiLog is on!
-- 業(yè)務(wù)1 start --
This is a controller about aop test!
-- 業(yè)務(wù)1 end  耗時5ms --

通知時機

以上我們通過一個簡單的例子,初步體驗了aop的魅力。接下來我們來討論以下各類通知的特點以及應(yīng)用時機問題。我們對的上面的切面類進行了修改,加上所有類型的通知。

@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* com.acelin.hello.study.springTest.aop.AspectController.*(..))")
    private void onePointcut(){}

    @Before("onePointcut()")
    public void before(){
        System.out.println("-- before");
    }

    @After("onePointcut()")
    public void after(JoinPoint joinPoint) throws NoSuchMethodException{
        System.out.println("-- after");
    }
    
    @AfterThrowing("onePointcut()")
    public void afterThrowing(){
        System.out.println("-- afterThrowing");
    }

    @AfterReturning("onePointcut()")
    public void afterReturning(){
        System.out.println("-- afterReturning");
    }
    
    @Around("onePointcut()")
    public Object around(ProceedingJoinPoint point)throws Throwable{

        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        /* 獲取方法上的注解 */
        ApiLog apiLog = method.getAnnotation(ApiLog.class);
        if (apiLog != null && apiLog.isOn()){
            System.out.println("ApiLog is on!");
        }

        Object[] objects = point.getArgs();
        String bussinessName = (String) objects[0];
        System.out.println("-- " + bussinessName + " start");
        long begin = System.currentTimeMillis();
        Object object = point.proceed();
        long end = System.currentTimeMillis();
        System.out.println("-- " + bussinessName + " end  耗時" + (end - begin) + "ms");
        return object;
    }
}

然后修改接口,怎加業(yè)務(wù)名稱的一個長度判斷,如果名稱太長,拋出異常,來模擬方法執(zhí)行過程中法僧異常

@RequestMapping("/test/1/{businessName}")
@ApiLog
public void testAop(@PathVariable("businessName") String businessName){
    System.out.println("This is a controller about aop test!");
    if (businessName.length() > 4){
        throw new RuntimeException("業(yè)務(wù)名稱太長!");
    }
}

- 正常情況

來看一下當(dāng)方法正常執(zhí)行的情況下,前置通知、后置通知、返回通知和環(huán)繞通知的應(yīng)用時機。

再次調(diào)用測試接口,可看到如下結(jié)果:

ApiLog is on!
-- 業(yè)務(wù) start
-- before
This is a controller about aop test!
-- afterReturning
-- after
-- 業(yè)務(wù) end  耗時6ms

- 異常情況

然后我們修改業(yè)務(wù)名稱為,使其超過規(guī)定長度導(dǎo)致觸發(fā)異常拋出,結(jié)果如下:

ApiLog is on!
-- 超級復(fù)雜的業(yè)務(wù) start
-- before
This is a controller about aop test!
-- afterThrowing
-- after

java.lang.RuntimeException: 業(yè)務(wù)名稱太長!

 at com.acelin.hello.study.springTest.aop.AspectController.testAop(AspectController.java:16)

從上面結(jié)果可以看出的,前置通知應(yīng)用于目標方法執(zhí)行前,然后當(dāng)方法正常執(zhí)行時,會在方法結(jié)束前執(zhí)行返回通知,如果發(fā)生異常,執(zhí)行異常通知,返回通知不執(zhí)行(因為方法已經(jīng)中斷,不正常返回),而后置通知的是不管方法執(zhí)行情況,都會在方法結(jié)束后執(zhí)行。環(huán)繞通知則包裹著以上所有流程。

總結(jié)

以上就是對AOP相關(guān)知識的入門,相關(guān)術(shù)語的解釋,以及SpringBoot集成SpringAOP的簡單應(yīng)用,,希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java入門絆腳石之Override和Overload的區(qū)別詳解

    Java入門絆腳石之Override和Overload的區(qū)別詳解

    重寫是子類對父類的允許訪問的方法的實現(xiàn)過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!重寫的好處在于子類可以根據(jù)需要,定義特定于自己的行為。重載是在一個類里面,方法名字相同,而參數(shù)不同。返回類型可以相同也可以不同
    2021-10-10
  • Java Fluent Mybatis 項目工程化與常規(guī)操作詳解流程篇 下

    Java Fluent Mybatis 項目工程化與常規(guī)操作詳解流程篇 下

    Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。國內(nèi)又以Mybatis用的多,基于mybatis上的增強框架,又有mybatis plus和TK mybatis等。今天我們介紹一個新的mybatis增強框架 fluent mybatis關(guān)于項目工程化與常規(guī)操作流程
    2021-10-10
  • Spring?Boot?接口加解密功能實現(xiàn)

    Spring?Boot?接口加解密功能實現(xiàn)

    在我們?nèi)粘5腏ava開發(fā)中,免不了和其他系統(tǒng)的業(yè)務(wù)交互,或者微服務(wù)之間的接口調(diào)用;如果我們想保證數(shù)據(jù)傳輸?shù)陌踩?,對接口出參加密,入?yún)⒔饷?,這篇文章主要介紹了Spring?Boot?接口加解密功能實現(xiàn),需要的朋友可以參考下
    2023-04-04
  • Spring BeanUtils忽略空值拷貝的方法示例代碼

    Spring BeanUtils忽略空值拷貝的方法示例代碼

    本文用示例介紹Spring(SpringBoot)如何使用BeanUtils拷貝對象屬性忽略空置,忽略null值拷貝屬性的用法,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2022-03-03
  • 解決IDEA使用Spring Initializr創(chuàng)建項目時無法連接到https://start.spring.io的問題

    解決IDEA使用Spring Initializr創(chuàng)建項目時無法連接到https://start.spring.io的問

    這篇文章主要介紹了解決IDEA使用Spring Initializr創(chuàng)建項目時無法連接到https://start.spring.io的問題,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • java中文及特殊字符的校驗方法

    java中文及特殊字符的校驗方法

    這篇文章主要為大家詳細介紹了java中文及特殊字符的校驗方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • 識別率很高的java文字識別技術(shù)

    識別率很高的java文字識別技術(shù)

    這篇文章主要為大家詳細介紹了識別率很高的java文字識別技術(shù),親測,希望對大家有幫助,感興趣的小伙伴們可以參考一下
    2016-08-08
  • JAVA二叉樹的基本操作

    JAVA二叉樹的基本操作

    這篇文章主要介紹了JAVA二叉樹的基本操作DEMO,想要詳情了解的小伙伴請接著看下文吧
    2021-08-08
  • Java 方法引用與ambda表達式的聯(lián)系

    Java 方法引用與ambda表達式的聯(lián)系

    這篇文章主要介紹了Java 方法引用與ambda表達式的聯(lián)系,方法引用通過方法的名字來指向一個方法, 方法引用同樣是Java 8 引入的新特性,而且和Lambda表達式有著不小的聯(lián)系,它同樣可以根據(jù)上下文進行推導(dǎo),進而可以簡化代碼
    2022-06-06
  • SpringBoot配置Profile實現(xiàn)多環(huán)境支持

    SpringBoot配置Profile實現(xiàn)多環(huán)境支持

    這篇文章主要介紹了SpringBoot配置Profile實現(xiàn)多環(huán)境支持操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論