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

詳解Java SpringAOP切面類

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

切面類是什么

簡單的來說,就是動態(tài)的在方法的指定位置添加指定的代碼。

為什么需要切面類?

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

什么意思呢?

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

在這里插入圖片描述

什么時候需要用切面類?

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

切面類有什么用?

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

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

日志的作用

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

日志如何實現(xiàn)

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

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

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

身份驗證、數(shù)據(jù)緩存、異常處理等非核心業(yè)務如果處理不好往往會導致核心業(yè)務代碼結構混亂。

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

切面類能完成這些任務

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

AOP的五大通知

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

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

通知是啥?簡單理解就是上面說到的輔助業(yè)務,我們在劃分切面的提取輔助業(yè)務代碼時候,會有以下情況

  • 需要在核心業(yè)務前執(zhí)行該輔助業(yè)務
  • 需要在核心業(yè)務執(zhí)行之后執(zhí)行該輔助業(yè)務
  • 需要在報錯時候執(zhí)行該輔助業(yè)務
  • 需要在返回結果是執(zhí)行該輔助業(yè)務
  • 需要在方法執(zhí)行之前之后異常時執(zhí)行該輔助業(yè)務

上面需要搞清的時后置通知和返回通知

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

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

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

在這里插入圖片描述

  • 動態(tài)代理(InvocationHandler):JDK原生的實現(xiàn)方式,需要被代理的目標類必須實現(xiàn)接口。因為這個技術要求代理對象和目標對象實現(xiàn)同樣的接口(兄弟兩個拜把子模式)。
  • cglib:通過繼承被代理的目標類(認干爹模式)實現(xiàn)代理,所以不需要目標類實現(xiàn)接口。
  • AspectJ:本質(zhì)上是靜態(tài)代理,將代理邏輯“織入”被代理的目標類編譯得到的字節(jié)碼文件,所以最終效果是動態(tài)的。weaver就是織入器。Spring只是借用了AspectJ中的注解。

一、準備工作

在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>

<!--在使用這個代碼的時候,我用IDEA沒有代碼提示,并且寫完會爆紅色,直接同步即可,不-->
    <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>

因為我們要使用的是AspectJ中的注解,所以需要導入

    <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>

測試類

@RunWith(SpringJUnit4ClassRunner.class)//這個需要spring-test依賴,使用后不需要創(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);
    }
}

這篇文章我們先用有接口的形式來寫切面類

文件結構

在這里插入圖片描述

切面類中有什么?

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

這些通知有什么用?

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

為什么命名為切面類?

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

在這里插入圖片描述

下面來看代碼

切面類

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

再來看看測試方法

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

結果:

在這里插入圖片描述

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

總結

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

相關文章

  • Java使用dom4j解析XML

    Java使用dom4j解析XML

    dom4j是一個開源的、基于Java的XML解析庫,而在Java中使用dom4j庫解析XML是一種常見的方法,下面就跟隨小編一起來學習一下Java如何使用dom4j解析XML吧
    2024-12-12
  • SpringCloud?集成Sentinel的實戰(zhàn)教程

    SpringCloud?集成Sentinel的實戰(zhàn)教程

    這篇文章主要介紹了SpringCloud?集成Sentinel的詳細過程,本文通過實例代碼圖文相結合給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2024-08-08
  • IDEA?database和datagrip無法下載驅(qū)動問題解決辦法

    IDEA?database和datagrip無法下載驅(qū)動問題解決辦法

    這篇文章主要給大家介紹了關于IDEA?database和datagrip無法下載驅(qū)動問題的解決辦法,文中通過代碼介紹的非常詳細,對大家學習或者使用idea具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-03-03
  • SpringBoot使用thymeleaf實現(xiàn)前端表格

    SpringBoot使用thymeleaf實現(xiàn)前端表格

    雖然現(xiàn)在流行前后端分離,但是后端模版在一些關鍵地方還是非常有用的,例如郵件模版、代碼模版等。當然也不排除一些古老的項目后端依然使用動態(tài)模版。Thymeleaf 簡潔漂亮、容易理解,并且完美支持 HTML5,可以直接打開靜態(tài)頁面,同時不新增標簽,只需增強屬性
    2022-10-10
  • Java利用Socket實現(xiàn)網(wǎng)絡通信功能

    Java利用Socket實現(xiàn)網(wǎng)絡通信功能

    在早期的網(wǎng)絡編程中,Socket是很常見的實現(xiàn)技術之一,比如早期的聊天室,就是基于這種技術進行實現(xiàn)的,另外現(xiàn)在有些消息推送,也可以基于Socket實現(xiàn),本文小編給大家介紹了Java利用Socket實現(xiàn)網(wǎng)絡通信功能的示例,需要的朋友可以參考下
    2023-11-11
  • MyBatis常見報錯問題及解決方案

    MyBatis常見報錯問題及解決方案

    這篇文章主要介紹了MyBatis常見報錯問題及解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • Springboot Redis設置key前綴的方法步驟

    Springboot Redis設置key前綴的方法步驟

    這篇文章主要介紹了Springboot Redis設置key前綴的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • 詳解@ConfigurationProperties實現(xiàn)原理與實戰(zhàn)

    詳解@ConfigurationProperties實現(xiàn)原理與實戰(zhàn)

    這篇文章主要介紹了詳解@ConfigurationProperties實現(xiàn)原理與實戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • Springboot 如何指定獲取自己寫的配置properties文件的值

    Springboot 如何指定獲取自己寫的配置properties文件的值

    這篇文章主要介紹了Springboot 如何指定獲取自己寫的配置properties文件的值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java中的自旋鎖spinlock詳解

    Java中的自旋鎖spinlock詳解

    這篇文章主要介紹了Java中的自旋鎖spinlock詳解,自旋鎖就是循環(huán)嘗試獲取鎖,不會放棄CPU時間片,減傷cup上下文切換,缺點是循環(huán)會消耗cpu,需要的朋友可以參考下
    2024-01-01

最新評論

罗定市| 宁都县| 汶川县| 法库县| 简阳市| 安宁市| 库伦旗| 乐东| 托克托县| 闽侯县| 额尔古纳市| 特克斯县| 浙江省| 安达市| 洪湖市| 田林县| 平罗县| 信阳市| 夏津县| 蚌埠市| 克什克腾旗| 长沙市| 龙井市| 定远县| 浪卡子县| 陇川县| 二手房| 凤山县| 宁德市| 万州区| 和顺县| 兰考县| 岳池县| 无极县| 高安市| 忻州市| 濮阳市| 全州县| 北辰区| 海盐县| 泗水县|