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

詳解Java SpringAOP切面類

 更新時(shí)間:2021年12月28日 17:07:41   投稿:BJT  
這篇文章主要為大家介紹了Java SpringAOP的切面類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

切面類是什么

簡(jiǎn)單的來(lái)說(shuō),就是動(dòng)態(tài)的在方法的指定位置添加指定的代碼。

為什么需要切面類?

在軟件開(kāi)發(fā)的過(guò)程中,有很多業(yè)務(wù),特別是在編寫(xiě)核心業(yè)務(wù)的時(shí)候,往往需要很多其他的輔助業(yè)務(wù),比如說(shuō)身份驗(yàn)證(銀行轉(zhuǎn)賬需要身份驗(yàn)證)、數(shù)據(jù)緩存、日志輸出。這些往往在某個(gè)核心業(yè)務(wù)中處于輔助的部分。這些輔助的任務(wù)都有個(gè)特點(diǎn),就是這些業(yè)務(wù)都處在核心業(yè)務(wù)的同一個(gè)切面上?

什么意思呢?

假如有加減乘除四個(gè)方法,方法開(kāi)始位置和方法結(jié)束位置只是一個(gè)標(biāo)志,方法執(zhí)行位置處是核心業(yè)務(wù),我們想在這四個(gè)方法的核心代碼前執(zhí)行一些準(zhǔn)備操作,那么我們可以在方法開(kāi)始位置和方法執(zhí)行位置之間加入一段代碼,那么這些準(zhǔn)備操作實(shí)際上就是在同一個(gè)切面上的。同理,在四個(gè)方法的任意處切一刀,都是一個(gè)切面。

在這里插入圖片描述

什么時(shí)候需要用切面類?

對(duì)于一些方法,抽取出來(lái)同一類非核心業(yè)務(wù),然后可以將提取出來(lái)的業(yè)務(wù)編寫(xiě)成一個(gè)切面類,切面類可以;例如加減乘除,加入日志功能,那么日志功能就是非核心業(yè)務(wù)。

切面類有什么用?

解決代碼混亂問(wèn)題,非核心業(yè)務(wù)和核心業(yè)務(wù)代碼處于同一個(gè)方法中會(huì)影響代碼的質(zhì)量,甚至可能會(huì)影響到核心業(yè)務(wù)

下面用日志功能來(lái)講解切面類怎么創(chuàng)建

日志的作用

  • 在數(shù)據(jù)處理之前顯示我們傳入的數(shù)據(jù)
  • 遇到異常返回
  • 處理結(jié)束顯示處理完成

日志如何實(shí)現(xiàn)

最簡(jiǎn)單的方法,在數(shù)據(jù)處理之前手動(dòng)輸出。

    public void receiveMoney(int receiveMoney) throws ReceiveMoneyException {
        System.out.println("[收錢]:參數(shù)為"+receiveMoney);
        System.out.println("[收錢]數(shù)據(jù)處理中。。。。");
        checkAmount(receiveMoney);
        System.out.println("[收錢]數(shù)據(jù)處理事務(wù)完成完成");
    }

這樣我們的日志功能就可以實(shí)現(xiàn)了,但是,這只是其中一個(gè)輔助業(yè)務(wù),一個(gè)項(xiàng)目中有很多業(yè)務(wù),各種繁瑣的功能和日志都實(shí)現(xiàn)在一個(gè)方法中,代碼結(jié)構(gòu)會(huì)無(wú)比的混亂,特別是一個(gè)日志功能和核心功能放在一起,很容易發(fā)生問(wèn)題,并且一個(gè)業(yè)務(wù)中往往還要很多其他非核心的業(yè)務(wù)需要處理,比如說(shuō)在接受錢之前,需要驗(yàn)明身份,來(lái)路不明的錢銀行不能直接接收,若身份核驗(yàn)正確,那么接收到錢后還得進(jìn)行數(shù)據(jù)緩存。

身份驗(yàn)證、數(shù)據(jù)緩存、異常處理等非核心業(yè)務(wù)如果處理不好往往會(huì)導(dǎo)致核心業(yè)務(wù)代碼結(jié)構(gòu)混亂。

那么怎樣能將日志功能、身份驗(yàn)證加入到核心業(yè)務(wù)方法之中,但是不影響核心業(yè)務(wù) 的代碼

切面類能完成這些任務(wù)

  • 切面類能動(dòng)態(tài)的在指定位置添加指定代碼

AOP的五大通知

AspectJ 支持 5 種類型的通知注解:

  • @Before: 前置通知, 在方法執(zhí)行之前執(zhí)行
  • @After: 后置通知, 在方法執(zhí)行之后執(zhí)行
  • @AfterRunning: 返回通知, 在方法返回結(jié)果之后執(zhí)行
  • @AfterThrowing: 異常通知, 在方法拋出異常之后
  • @Around: 環(huán)繞通知, 圍繞著方法執(zhí)行

通知是啥?簡(jiǎn)單理解就是上面說(shuō)到的輔助業(yè)務(wù),我們?cè)趧澐智忻娴奶崛≥o助業(yè)務(wù)代碼時(shí)候,會(huì)有以下情況

  • 需要在核心業(yè)務(wù)前執(zhí)行該輔助業(yè)務(wù)
  • 需要在核心業(yè)務(wù)執(zhí)行之后執(zhí)行該輔助業(yè)務(wù)
  • 需要在報(bào)錯(cuò)時(shí)候執(zhí)行該輔助業(yè)務(wù)
  • 需要在返回結(jié)果是執(zhí)行該輔助業(yè)務(wù)
  • 需要在方法執(zhí)行之前之后異常時(shí)執(zhí)行該輔助業(yè)務(wù)

上面需要搞清的時(shí)后置通知和返回通知

返回通知(after-returning):當(dāng)核心業(yè)務(wù)代碼執(zhí)行完成后執(zhí)行,發(fā)生異常不執(zhí)行

后置通知(after):不論目標(biāo)方法是否發(fā)生異常都會(huì)執(zhí)行,若無(wú)異常,則執(zhí)行順序在返回通知之后

Spring AOP類的實(shí)現(xiàn)技術(shù)

在這里插入圖片描述

  • 動(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:通過(guò)繼承被代理的目標(biāo)類(認(rèn)干爹模式)實(shí)現(xiàn)代理,所以不需要目標(biāo)類實(shí)現(xiàn)接口。
  • AspectJ:本質(zhì)上是靜態(tài)代理,將代理邏輯“織入”被代理的目標(biāo)類編譯得到的字節(jié)碼文件,所以最終效果是動(dòng)態(tài)的。weaver就是織入器。Spring只是借用了AspectJ中的注解。

一、準(zhǔn)備工作

在maven的pom.xml中加入如下代碼

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>Spring-AOP</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.14</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.3.14</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.3.14</version>
    </dependency>

<!--在使用這個(gè)代碼的時(shí)候,我用IDEA沒(méi)有代碼提示,并且寫(xiě)完會(huì)爆紅色,直接同步即可,不-->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    </dependencies>
</project>

因?yàn)槲覀円褂玫氖茿spectJ中的注解,所以需要導(dǎo)入

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>

springconfig

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <aop:aspectj-autoproxy/>
    <context:component-scan base-package="com"/>
</beans>

測(cè)試類

@RunWith(SpringJUnit4ClassRunner.class)//這個(gè)需要spring-test依賴,使用后不需要?jiǎng)?chuàng)建IOC容器
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class AOPTEST {
    @Autowired
    private Calc calc;
    @Test
    public void testAnnotationAOP(){
        int add=calc.add(10,0);
        System.out.println("外部 add"+add);
    }
}

這篇文章我們先用有接口的形式來(lái)寫(xiě)切面類

文件結(jié)構(gòu)

在這里插入圖片描述

切面類中有什么?

  • 前置通知(Before):在目標(biāo)方法執(zhí)行之前執(zhí)行某段代碼
  • 后置通知(AfterReturning):在目標(biāo)方執(zhí)行完成后執(zhí)行,如果目標(biāo)方法異常,則后置通知不再執(zhí)行某段代碼
  • 異常通知(Afterthrowing):目標(biāo)方法拋出異常的時(shí)候執(zhí)行某段代碼
  • 最終通知(After);不管目標(biāo)方法是否有異常都會(huì)執(zhí)行,相當(dāng)于try…catch…finally中的finally。
  • 環(huán)繞通知(Around):可以控制目標(biāo)方法是否執(zhí)行

這些通知有什么用?

  • 不需要再核心代碼內(nèi)部添加多余的代碼,而是在調(diào)用核心代碼前、后、拋異常、結(jié)束時(shí)調(diào)用某部分代碼。
  • 這里涉及到了反射的知識(shí),因?yàn)檫@些通知的實(shí)現(xiàn)底層就是動(dòng)態(tài)代理或cglib。簡(jiǎn)單來(lái)說(shuō),就是在調(diào)用核心代碼前,調(diào)用的方法會(huì)被攔截下來(lái),然后執(zhí)行切面類中的某段代碼。

為什么命名為切面類?

首先要知道一點(diǎn),切面類可以對(duì)很多方法或者很多類切面,主要看你想實(shí)現(xiàn)怎么樣的功能。比如說(shuō)我們想在方法執(zhí)行之前調(diào)用日志功能,那么我們要把這些方法在執(zhí)行之前“切開(kāi)”,然后在方法內(nèi)“加入”日志輸出。因?yàn)檫@些事情都是切面類做的,所以才有這樣的名稱。

在這里插入圖片描述

下面來(lái)看代碼

切面類

@Aspect
@Component
public class LogAspect {
    //前置通知
    @Before(value = "execution(public int com.Calc.add(int ,int ))")
    public void printLogBefore(){
        System.out.println("[AOP前置通知]方法開(kāi)始了");
    }
    //后置通知
    @AfterReturning(value = "execution(public int com.Calc.add(int ,int ))")
    //在返回通知中獲取目標(biāo)方法返回值分為兩步,給returning設(shè)置一個(gè)名稱,然后使用該名稱在通知方法中聲明一個(gè)對(duì)應(yīng)的形參
    public void printLogAfterSuccess(){
        System.out.println("[AOP返回通知]方法成功返回了");
    }
    //異常通知
    @AfterThrowing(value ="execution(public int com.Calc.add(int ,int ))")
    public void printLogAfterException(){
        System.out.println("[AOP異常通知]方法拋出異常");
    }
    //結(jié)束通知
    @After("execution(public int com.Calc.add(int ,int ))")
    public void printLogFinish(){
        System.out.println("[AOP結(jié)束通知]方法結(jié)束了");
    }
}

再來(lái)看看測(cè)試方法

    @Test
    public void testAnnotationAOP(){
        int add=calc.add(10,0);//調(diào)用
        System.out.println("外部 add"+add);
    }

結(jié)果:

在這里插入圖片描述

可以看見(jiàn),切面類成功在Calculator中實(shí)現(xiàn)了日志功能

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • SpringBoot深入分析webmvc和webflux的區(qū)別

    SpringBoot深入分析webmvc和webflux的區(qū)別

    這篇文章主要介紹了SpringBoot深入分析webmvc和webflux的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-02-02
  • Mybatis使用Collection屬性的示例代碼

    Mybatis使用Collection屬性的示例代碼

    本文主要介紹了Mybatis使用Collection屬性的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java中FTPClient上傳中文目錄、中文文件名亂碼問(wèn)題解決方法

    Java中FTPClient上傳中文目錄、中文文件名亂碼問(wèn)題解決方法

    這篇文章主要介紹了Java中FTPClient上傳中文目錄、中文文件名亂碼問(wèn)題解決方法,本文使用apache-commons-net工具包時(shí)遇到這個(gè)問(wèn)題,解決方法很簡(jiǎn)單,需要的朋友可以參考下
    2015-05-05
  • SpringMVC @ControllerAdvice使用場(chǎng)景

    SpringMVC @ControllerAdvice使用場(chǎng)景

    這篇文章主要介紹了SpringMVC @ControllerAdvice使用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • java多線程編程之線程的生命周期

    java多線程編程之線程的生命周期

    線程要經(jīng)歷開(kāi)始(等待)、運(yùn)行、掛起和停止四種不同的狀態(tài)。這四種狀態(tài)都可以通過(guò)Thread類中的方法進(jìn)行控制。下面給出了Thread類中和這四種狀態(tài)相關(guān)的方法
    2014-01-01
  • 深入淺出Java mvc_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    深入淺出Java mvc_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了MVC的基礎(chǔ)知識(shí),MVC是一個(gè)框架模式,它強(qiáng)制性的使應(yīng)用程序的輸入、處理和輸出分開(kāi),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • springboot使用redis對(duì)單個(gè)對(duì)象進(jìn)行自動(dòng)緩存更新刪除的實(shí)現(xiàn)

    springboot使用redis對(duì)單個(gè)對(duì)象進(jìn)行自動(dòng)緩存更新刪除的實(shí)現(xiàn)

    本文主要介紹了springboot使用redis對(duì)單個(gè)對(duì)象進(jìn)行自動(dòng)緩存更新刪除的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 使用FeignClient調(diào)用POST表單Body內(nèi)沒(méi)有參數(shù)問(wèn)題

    使用FeignClient調(diào)用POST表單Body內(nèi)沒(méi)有參數(shù)問(wèn)題

    這篇文章主要介紹了使用FeignClient調(diào)用POST表單Body內(nèi)沒(méi)有參數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java實(shí)現(xiàn)經(jīng)典游戲飛機(jī)大戰(zhàn)-I的示例代碼

    Java實(shí)現(xiàn)經(jīng)典游戲飛機(jī)大戰(zhàn)-I的示例代碼

    《飛機(jī)大戰(zhàn)-I》是一款融合了街機(jī)、競(jìng)技等多種元素的經(jīng)典射擊手游。本文將利用java語(yǔ)言實(shí)現(xiàn)這游戲,文中采用了swing技術(shù)進(jìn)行了界面化處理,感興趣的可以了解一下
    2022-02-02
  • myeclipse無(wú)法部署項(xiàng)目問(wèn)題及解決方法

    myeclipse無(wú)法部署項(xiàng)目問(wèn)題及解決方法

    最近小編遇到到棘手的問(wèn)題,myeclipse無(wú)法部署項(xiàng)目,點(diǎn)擊這個(gè)部署按鈕沒(méi)有反應(yīng)。怎么解決呢,下面小編給大家代理的myeclipse無(wú)法部署項(xiàng)目問(wèn)題及解決方法 ,感興趣的朋友一起看看吧
    2018-10-10

最新評(píng)論