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

詳解Spring Aop實現(xiàn)日志收集和重復(fù)屬性賦值

 更新時間:2024年10月11日 16:23:32   作者:王五周八  
AOP(面向切面編程)是一種編程思想,它允許開發(fā)者將公共邏輯(如日志記錄、權(quán)限校驗等)抽離出來,使得可以更專注于業(yè)務(wù)邏輯的開發(fā),SpringAOP通過定義切面、切入點、通知等概念,本文介紹Spring Aop實現(xiàn)日志收集和重復(fù)屬性賦值的相關(guān)操作,感興趣的朋友一起看看吧

Spring Aop實現(xiàn)日志收集和重復(fù)屬性賦值

簡介

? AOP(Aspect-Oriented Programming),即面向切面編程,用人話說就是把公共的邏輯抽出來,讓開發(fā)者可以更專注于業(yè)務(wù)邏輯開發(fā)。

? 和IOC一樣,AOP也指的是一種思想。AOP思想是OOP(Object-Oriented Programming)的補充。OOP是面向類和對象的,但是AOP則是面向不同切面的。一個切面可以橫跨多個類和對象去操作,極大的豐富了開發(fā)者的使用方式,提高了開發(fā)效率。

譬如,一個訂單的創(chuàng)建,可能需要以下步驟:

  • 權(quán)限校驗
  • 事務(wù)管理
  • 創(chuàng)建訂單
  • 日志打印

如果使用AOP思想,我們就可以把這四步當成四個“切面”,讓業(yè)務(wù)人員專注開發(fā)第三個切面,其他三個切面則是基礎(chǔ)的通用邏輯,統(tǒng)一交給AOP封裝和管理。

Spring AOP有如下概念:

術(shù)語翻譯釋義
Aspect切面切面由切入點和通知組成,它既包含了橫切邏輯的定義,也包括了切入點的定義。切面是一個橫切關(guān)注點的模塊化,一個切面能夠包含同一個類型的不同增強方法,比如說事務(wù)處理和日志處理可以理解為兩個切面。
PointCut切入點切入點是對連接點進行攔截的條件定義,決定通知應(yīng)該作用于截哪些方法。(充當where角色,即在哪里做)
Advice通知通知定義了通過切入點攔截后,應(yīng)該在連接點做什么,是切面的具體行為。(充當what角色,即做什么)
Target目標對象目標對象指將要被增強的對象,即包含主業(yè)務(wù)邏輯的類對象?;蛘哒f是被一個或者多個切面所通知的對象。
JoinPoint連接點連接點是程序在運行時的執(zhí)行點,這個點可以是正在執(zhí)行的方法,或者是正在拋出的異常。因為Spring只支持方法類型的連接點,所以在Spring中連接點就是運行時刻被攔截到的方法。連接點由兩個信息確定:+ 方法(表示程序執(zhí)行點,即在哪個目標方法)+ 相對點(表示方位,即目標方法的什么位置,比如調(diào)用前,后等)
Weaving織入織入是將切面和業(yè)務(wù)邏輯對象連接起來, 并創(chuàng)建通知代理的過程??椚肟梢栽诰幾g時,類加載時和運行時完成。在編譯時進行織入就是靜態(tài)代理,而在運行時進行織入則是動態(tài)代理。

對于通知類型來說:

Before Advice連接點執(zhí)行前執(zhí)行的邏輯
After returning advice連接點正常執(zhí)行(未拋出異常)后執(zhí)行的邏輯
After throwing advice連接點拋出異常后執(zhí)行的邏輯
After finally advice無論連接點是正常執(zhí)行還是拋出異常,在連接點執(zhí)行完畢后執(zhí)行的邏輯
Around advice該通知可以非常靈活的在方法調(diào)用前后執(zhí)行特定的邏輯

代碼實現(xiàn)

1、創(chuàng)建注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value() default "";
}

2、切面類

@Aspect
@Slf4j
@Component
public class LogAspect {
    /**
     * 切入點
     */
    @Pointcut("execution(* com.zh.cn.*.*.*(..)) && @annotation(com.zh.cn.annotation.Log)")
    public void LogAspect(){
    }
    @Before("LogAspect()")
    public void before(JoinPoint joinPoint){
        //收集日志系統(tǒng)
        log.info("日志收集---前置通知");
        //獲取日志收集中的實體類
        log.info("參數(shù):{}",joinPoint);
        //獲取basePojo實體類
        Object[] args = joinPoint.getArgs();
        Object entity = args[0];
        try {
            Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", Date.class);
            Method setUpdateName = entity.getClass().getDeclaredMethod("setUpdateName", String.class);
            //通過反射為對象賦值
            setUpdateTime.invoke(entity,new Date());
            setUpdateName.invoke(entity,"zh");
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        //收集日志
        //~~~~
        log.info("日志收集---后置通知");
    }
}

3、controller層

/**
 * @Description:
 * @author:<a href="2358853434@qq.com"></a> zh
 * @Create : 2024/10/5
 **/
@RestController
@RequestMapping("/order/v1")
public class OrderController {
    @Resource
    private OrderService orderService;
    @GetMapping("/update")
    public Result update() {
        Order order = new Order();
        order.setId(1292071939041697792L);
        order.setName("測試商品");
        order.setNum(128L);
        return orderService.update(order);
    }
    @GetMapping("/insert")
    public Result insert(){
        return  Result.success();
    }
}

4、service層

@Service
@Slf4j
public class OrderServiceimpl implements OrderService {
    @Resource
    RedisTemplate<String,String> redisTemplate;
    @Resource
    RedisDistributedLock redisDistributedLock;
    /**
     * 更新訂單接口
     * @param order
     * @return
     */
    @Log
    public Result update(Order order) {
        log.info("update開始,訂單號:{}",order.getId()+"order:"+order);
        //加鎖成功
        while(redisDistributedLock.tryLock("order:"+order.getId()+":"+Thread.currentThread().getId(), "requestId", 10)) {
            //執(zhí)行訂單減減
            log.info("加鎖成功"+Thread.currentThread().getId());
            redisTemplate.opsForValue().set("order:"+order.getId(), order.toString());
            break;
        }
        if (redisDistributedLock.unlock("order:"+order.getId()+":"+Thread.currentThread().getId(),"requestId")) {
            log.info("update結(jié)束,訂單號:{}",order.getId());
            return Result.success();
        }
        return Result.error("下單失敗");
    }
}

5、測試 測試用例

由于項目中加了spring-security的相關(guān)依賴,需要配置Authorization,不需要的友友請自行刪除

GET http://localhost:19002/order/v1/update
Authorization: Basic cm9vdDpyb290

結(jié)果

到此這篇關(guān)于Spring Aop實現(xiàn)日志收集和重復(fù)屬性賦值的文章就介紹到這了,更多相關(guān)Mysql全文檢索內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL 5.6 中TIMESTAMP with implicit DEFAULT value is deprecated錯誤

    MySQL 5.6 中TIMESTAMP with implicit DEFAULT value is deprecat

    安裝mysql的時候出現(xiàn)TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details),可以參考下面的方法解決
    2015-08-08
  • MySQL中字段的實際長度的實現(xiàn)示例代碼

    MySQL中字段的實際長度的實現(xiàn)示例代碼

    MySQL字段的存儲長度不僅取決于數(shù)據(jù)類型,還受字符編碼和存儲內(nèi)容的影響,CHAR和VARCHAR字段可以使用LENGTH()和CHAR_LENGTH()函數(shù)獲取長度信息,下面就來具體介紹一下
    2024-09-09
  • 手把手教你MySQL運算符

    手把手教你MySQL運算符

    運算符是告訴MySQL執(zhí)行特定算數(shù)或邏輯操作的符號,下面這篇文章主要給大家介紹了關(guān)于MySQL運算符的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-03-03
  • 解決mysql 組合AND和OR帶來的問題

    解決mysql 組合AND和OR帶來的問題

    這篇文章主要介紹了解決mysql 組合AND和OR帶來的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Windows中Mysql啟動失敗的完美解決方案

    Windows中Mysql啟動失敗的完美解決方案

    這篇文章主要介紹了Windows中Mysql啟動失敗解決方案,mysql服務(wù)啟動失敗分為2種情況給大家詳細介紹,針對每一種給大家詳細解決,需要的朋友可以參考下
    2022-10-10
  • MySQL分區(qū)表的正確使用方法

    MySQL分區(qū)表的正確使用方法

    這篇文章主要給大家介紹了關(guān)于MySQL分區(qū)表的正確使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-01-01
  • MYSQL數(shù)據(jù)庫表結(jié)構(gòu)優(yōu)化方法詳解

    MYSQL數(shù)據(jù)庫表結(jié)構(gòu)優(yōu)化方法詳解

    這篇文章主要介紹了MYSQL數(shù)據(jù)庫表結(jié)構(gòu)優(yōu)化方法,總結(jié)分析了mysql針對表結(jié)構(gòu)優(yōu)化的數(shù)據(jù)類型選擇、范式化操作、表的拆分等相關(guān)使用技巧,需要的朋友可以參考下
    2019-08-08
  • mysql 顯示SQL語句執(zhí)行時間的代碼

    mysql 顯示SQL語句執(zhí)行時間的代碼

    查看 MySQL 語法 詳細執(zhí)行時間 與 CPU/記憶體使用量: MySQL Query Profiler
    2009-08-08
  • mysql如何將表結(jié)構(gòu)導(dǎo)出到excel

    mysql如何將表結(jié)構(gòu)導(dǎo)出到excel

    這篇文章主要介紹了mysql如何將表結(jié)構(gòu)導(dǎo)出到excel,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫,感興趣的朋友可以了解下
    2020-09-09
  • MySQL使用全庫備份數(shù)據(jù)恢復(fù)單表數(shù)據(jù)的方法

    MySQL使用全庫備份數(shù)據(jù)恢復(fù)單表數(shù)據(jù)的方法

    這篇文章主要給大家介紹了關(guān)于MySQL使用全庫備份數(shù)據(jù)恢復(fù)單表數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用mysql具有一定的參考學習價值,需要的朋友們下面來一起看看吧
    2018-12-12

最新評論

晋江市| 济阳县| 晴隆县| 西宁市| 达拉特旗| 普洱| 凤冈县| 阜宁县| 图木舒克市| 郸城县| 西华县| 大化| 铅山县| 阜平县| 库尔勒市| 鹤峰县| 盐津县| 奎屯市| 来安县| 甘泉县| 彭泽县| 加查县| 江西省| 嵩明县| 陵川县| 庆安县| 新野县| 吉安市| 博爱县| 盈江县| 商洛市| 承德县| 班玛县| 江孜县| 嘉祥县| 方城县| 定襄县| 柳林县| 波密县| 玉环县| 永吉县|