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

SpringBoot 整合Lock4j 分布式鎖深度使用案例講解

 更新時間:2025年07月28日 10:05:21   作者:逆風飛翔的小叔  
本文介紹SpringBoot分布式鎖框架Lock4j,支持Redis、Zookeeper等多種存儲實現(xiàn),通過注解和AOP簡化鎖管理,提供并發(fā)控制、防止重復提交等場景應用,并支持自定義執(zhí)行器和key生成策略,適用于高并發(fā)和異構系統(tǒng)需求,感興趣的朋友一起看看吧

一、前言

日常開發(fā)中使用springboot框架進行微服務開發(fā)時,遇到需要控制并發(fā)造成的問題時,比較常用的做法是使用分布式鎖進行控制,基于分布式鎖的實現(xiàn),到目前為止也有很多開源實現(xiàn),使用比較多的像基于redis的分布式鎖,基于zookeeper的分布式鎖,本文再來介紹另一種比較高效的分布式鎖實現(xiàn),即lock4j,將通過案例演示下如何使用lock4j做分布式鎖。

二、Lock4j 概述

2.1 Lock4j 介紹

2.1.1 Lock4j 是什么

Lock4j 是一個基于 Spring Boot 的分布式鎖框架,旨在簡化分布式系統(tǒng)中鎖的實現(xiàn)和管理。項目入口:lock4j: 基于Spring AOP 的聲明式和編程式分布式鎖,支持RedisTemplate、Redisson、Zookeeper

2.1.2 Lock4j 主要特征

Lock4j是一個輕量級的分布式鎖框架,它支持多種鎖實現(xiàn),包括Redis、Zookeeper等,并通過Spring AOP進行集成,使得開發(fā)者可以輕松地在Spring應用中使用分布式鎖。它的設計目標是簡單易用,同時提供高性能和高可靠性。具體來說,包括下面的主要特征:

  • 注解驅(qū)動:通過簡單的注解即可實現(xiàn)方法級別的鎖控制
  • 多種鎖實現(xiàn):支持多種底層鎖實現(xiàn)方式
  • 可擴展:支持自定義鎖的實現(xiàn)
  • 與Spring生態(tài)集成:無縫集成Spring框架

2.1.3 Lock4j 技術特點

Lock4j 作為一款上手簡單,使用高效的分布式緩存技術框架,具備如下特點和優(yōu)勢:

  • 使用高效:
    • Lock4j采用了高效的鎖機制,能夠在高并發(fā)場景下保持穩(wěn)定的性能。其底層實現(xiàn)充分利用了Redis和Zookeeper等存儲系統(tǒng)的特性,確保鎖操作的快速響應。
  • 簡單易用:
    • 通過簡單的API和Spring AOP集成,開發(fā)者可以快速上手并實現(xiàn)分布式鎖。Lock4j提供了詳細的文檔和示例代碼,幫助開發(fā)者快速理解和使用。
  • 鎖支持類型豐富:
    • 支持多種底層存儲,滿足不同應用場景的需求。無論是高性能的Redis,還是強一致性的Zookeeper,Lock4j都能提供相應的支持。
  • 提供監(jiān)控和日志:
    • 提供豐富的監(jiān)控和日志功能,幫助開發(fā)者了解鎖的使用情況和性能表現(xiàn)。通過監(jiān)控界面,開發(fā)者可以實時查看鎖的狀態(tài)和性能指標。

2.2 Lock4j 支持的鎖類型

Lock4j支持多種類型鎖,通過底層存儲(如Redis或Zookeeper)來實現(xiàn)分布式鎖。支持的鎖類型包括:

  • Redis鎖:基于Redis實現(xiàn)的分布式鎖
  • Zookeeper鎖:基于Zookeeper實現(xiàn)的分布式鎖
  • 數(shù)據(jù)庫鎖:基于數(shù)據(jù)庫實現(xiàn)的鎖
  • 內(nèi)存鎖:本地JVM鎖(適用于單機環(huán)境)

2.3 Lock4j 工作原理

什么是鎖?鎖是一種同步機制,用于控制多線程對共享資源的訪問。在分布式系統(tǒng)中,鎖的實現(xiàn)更加復雜,因為需要在多個節(jié)點之間進行協(xié)調(diào)。Lock4j 作為分布式鎖框架,其核心原理是通過協(xié)調(diào)多個分布式節(jié)點對共享資源的訪問,確保在分布式環(huán)境下同一時間只有一個節(jié)點能夠執(zhí)行受保護的代碼塊。Lock4j通過底層存儲(如Redis、Zookeeper等)來實現(xiàn)分布式鎖。不同的存儲組件在具體的實現(xiàn)上稍有差別,但是其核心原理是類似的,下面是Lock4j 的基本工作原理:

  • 獲取鎖:
    • 當一個節(jié)點需要訪問共享資源時,它會向底層存儲發(fā)送請求以獲取鎖。請求中包含鎖的唯一標識和節(jié)點信息。
  • 鎖的持有:
    • 如果鎖可用,節(jié)點將持有該鎖,并可以安全地訪問共享資源。持有鎖的節(jié)點需要定期向存儲系統(tǒng)發(fā)送心跳信號,以保持鎖的有效性。
  • 釋放鎖:
    • 訪問完成后,節(jié)點會釋放鎖,使得其他節(jié)點可以獲取鎖并訪問資源。釋放鎖時,節(jié)點需要確保鎖的狀態(tài)已更新,以避免其他節(jié)點誤認為鎖仍然被持有。

2.4 Lock4j 應用場景

Lock4j 作為分布式鎖框架,適用于各種需要協(xié)調(diào)分布式系統(tǒng)資源訪問的場景。下面列舉了幾種常用的應用場景:

  • 防止重復提交/重復請求處理
    • 典型場景
    • 用戶快速多次點擊提交按鈕
    • 消息隊列消費者重復消費同一條消息
    • 定時任務重復執(zhí)行
  • 分布式鎖并發(fā)控制
    • 典型場景
    • 全局配置更新
    • 賬戶余額變更
    • 庫存扣減(防止超賣)
  • 定時任務防重復執(zhí)行
    • 典型場景
      • 分布式環(huán)境下多個實例的定時任務
      • 長時間執(zhí)行的批處理任務
  • 分布式緩存
    • 典型場景
      • 緩存擊穿保護
      • 緩存一致性維護
  • 關鍵業(yè)務流程串行化處理
    • 典型場景
      • 支付訂單處理
      • 文件導入導出
      • 數(shù)據(jù)遷移任務
  • 分布式文件系統(tǒng)
    • 在分布式文件系統(tǒng)中,多個節(jié)點可能會同時訪問和修改文件。
    • 通過使用Lock4j,可確保文件的一致性,避免數(shù)據(jù)損壞。例如,在云存儲系統(tǒng)中,多個節(jié)點可能會同時上傳和下載文件,通過分布式鎖可以確保文件數(shù)據(jù)的完整性。

三、springboot 整合lock4j使用案例

接下來通過案例詳細演示如何基于springboot整合lock4j進行代碼操作詳解。

3.1 前置準備

3.1. 1 導入依賴

創(chuàng)建一個springboot工程,導入下面的依賴

  • <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.4</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>
        <!-- 使用lock4j實現(xiàn)分布式鎖   https://gitee.com/baomidou/lock4j/-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>lock4j-core</artifactId>
            <version>2.2.5</version>
        </dependency>
        <!--添加開源分布式鎖Lock4j-->
        <!--若使用redisTemplate作為分布式鎖底層,則需要引入-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
            <version>2.2.5</version>
        </dependency>
    </dependencies>

3.2 基于Redis實現(xiàn)分布式鎖

基于Redis的實現(xiàn)是很常用的整合使用方式,當使用 Redis 作為底層存儲時,Lock4j 主要依賴 Redis 的以下特性:

  • SETNX 命令(或 SET 命令的 NX 選項):原子性地設置鍵值,只有鍵不存在時才會設置成功
  • 過期時間:避免死鎖
  • Lua 腳本:保證解鎖操作的原子性

下面看具體的整合和使用過程。

3.2.1 添加配置文件信息

在工程的配置文件中添加下面的信息

  • 需要注意的是,配置文件中設置的lock4j的幾個核心參數(shù)信息是全局生效的,比如acquire-timeout,這里全局設置的是3秒,但如果你在注解中再次配置了,則會覆蓋配置文件中的這個值;
server:
  port: 8082
lock4j:
  type: redis
  acquire-timeout: 3000  # 獲取鎖超時時間(毫秒)
  expire: 30000   # 鎖過期時間(毫秒)
  retry-interval: 100  # 獲取鎖失敗重試間隔(毫秒)
  #redis的鏈接配置信息
  redis:
    host: localhost
    database: 1
    port: 6379

3.2.2 添加測試接口

在工程中增加如下接口,方便測試

package com.congge.web;
import com.baomidou.lock.annotation.Lock4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LockController {
    //localhost:8082/testLock
    @Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 10000)
    @GetMapping("/testLock")
    public Object testLock(){
        long threadId = Thread.currentThread().getId();
        System.out.println(threadId + " : 獲取到了鎖,準備執(zhí)行業(yè)務邏輯");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return "testLock";
    }
}

在上面這段代碼中,在接口上面增加了一個 @Lock4j的注解,使用該注解即可實現(xiàn)分布式鎖的功能,并且設置了注解中其他的參數(shù),其核心參數(shù)包括:

  • key:鎖的鍵,支持SpEL表達式
  • expire:鎖的過期時間(毫秒)
  • timeout:獲取鎖的超時時間(毫秒)
  • retry:獲取鎖失敗后的重試間隔(毫秒)

3.2.3 效果測試

在postman中模擬一下多線程的并發(fā)測試

然后通過控制臺的結果輸出不難看出,多個線程請求過來的時候,由于分布式鎖的存在,所以未獲取到鎖的請求將會進行排隊,等待前面的線程釋放鎖,拿到鎖之后才能執(zhí)行

3.3 基于Redission 實現(xiàn)

使用Redission 的實現(xiàn)方式與Redis的實現(xiàn)差不多,首先需要導入下面的依賴,配置文件信息和接口代碼不用動,然后啟動工程后再次測試,可以得到相同的效果。

3.4 基于Zookeeper實現(xiàn)

基于 Zookeeper 的實現(xiàn)主要是利用了zk的臨時順序節(jié)點來實現(xiàn),還記得在使用zk實現(xiàn)分布式鎖的機制嗎,主要流程如下:

  • 在指定路徑下創(chuàng)建臨時順序節(jié)點
  • 判斷當前節(jié)點是否為最小序號節(jié)點
  • 如果是則獲取鎖,否則監(jiān)聽前一個節(jié)點的刪除事件

下面來看如何在代碼中集成和使用。

3.4.1 啟動zk服務

為了在代碼中集成并使用zookeeper,需要本地或服務器啟動一個zookeeper服務,這里直接在本機啟動

3.4.2 導入下面的依賴

在pom文件中導入下面的依賴

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>lock4j-zookeeper-spring-boot-starter</artifactId>
    <version>2.2.5</version>
</dependency>

3.4.3 添加配置信息

在配置文件中添加下面的配置信息

#使用redis作為分布式鎖
spring:
  coordinate:
    zookeeper:
      zkServers: 127.0.0.1:2181

3.4.4 添加測試接口

增加一個測試接口方便測試看效果

//localhost:8082/testZkLock
@Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 10000, executor = ZookeeperLockExecutor.class)
@GetMapping("/testZkLock")
public Object testZkLock(){
    long threadId = Thread.currentThread().getId();
    System.out.println(threadId + " : 獲取到了zk的鎖,準備執(zhí)行業(yè)務邏輯");
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return "testLock";
}

3.4.5 模擬并發(fā)測試

在postman中,使用并發(fā)調(diào)用接口的方式進行測試

通過控制臺輸出效果可以看到,有了分布式鎖的控制,可以確保請求的有序執(zhí)行

四、lock4j功能擴展

如果默認的配置還不能滿足實際的需求場景時,還可以使用lock4j提供的一些擴展點做補充,下面介紹幾個點。

4.1 自定義執(zhí)行器作用

lock4j 的自定義執(zhí)行器主要用于擴展和定制分布式鎖的實現(xiàn)方式

4.1.1 支持不同的分布式鎖實現(xiàn)

作用:允許集成各種分布式鎖技術,而不僅限于框架默認提供的幾種。

典型場景

  • 當項目使用非主流分布式協(xié)調(diào)服務時(如非Redis、Zookeeper等)
  • 需要接入公司自研的分布式鎖服務
  • 使用云服務商特有的分布式鎖服務(如AWS DynamoDB Lock Client)

4.1.2 定制鎖的獲取和釋放邏輯

作用:完全控制鎖的獲取和釋放過程,實現(xiàn)特殊業(yè)務需求。

典型場景

  • 需要實現(xiàn)特定等待策略(如指數(shù)退避)
  • 需要添加額外的鎖校驗邏輯(如業(yè)務狀態(tài)檢查)
  • 需要記錄詳細的鎖競爭指標和日志

4.1.3 適配特殊業(yè)務需求

作用:解決標準分布式鎖無法滿足的特殊業(yè)務場景。

典型場景

  • 需要實現(xiàn)租約機制(lease-based locking)
  • 需要支持不同級別的鎖(如讀鎖/寫鎖)
  • 需要實現(xiàn)鎖的自動續(xù)期功能

4.1.4 性能優(yōu)化

作用:針對特定環(huán)境優(yōu)化鎖的性能表現(xiàn)。

典型場景

  • 針對高并發(fā)場景優(yōu)化鎖實現(xiàn)
  • 減少網(wǎng)絡往返次數(shù)
  • 實現(xiàn)本地緩存加速

4.1.5 增強可靠性

作用:提供更健壯的鎖機制,防止極端情況下的問題。

典型場景

  • 處理時鐘漂移問題
  • 實現(xiàn)更安全的鎖釋放機制
  • 防止鎖過期但業(yè)務未完成的情況

4.1.6 統(tǒng)一鎖管理

作用:在異構環(huán)境中提供一致的鎖管理接口。

典型場景

  • 混合使用多種鎖實現(xiàn)(如部分用Redis,部分用數(shù)據(jù)庫)
  • 需要統(tǒng)一的監(jiān)控和管理界面
  • 實現(xiàn)鎖的降級策略

4.2 自定義執(zhí)行器使用

接下來通過兩個案例演示下如何使用自定義執(zhí)行器

4.2.1 基于zk的自定義執(zhí)行器

添加一個自定義類,繼承抽象類AbstractLockExecutor并重寫內(nèi)部的幾個核心方法,參考下面的代碼

package com.congge.config;
import com.baomidou.lock.executor.AbstractLockExecutor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.imps.CuratorFrameworkState;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Slf4j
@RequiredArgsConstructor
/**
 * 基于zk的分布式鎖執(zhí)行器 , 使用CuratorFramework作為ZooKeeper客戶端,實現(xiàn)鎖的獲取和釋放。
 */
@Component
public class MyZookeeperLockExecutor extends AbstractLockExecutor<InterProcessMutex> {
    private final CuratorFramework curatorFramework;
    /**
     * 嘗試獲取分布式鎖
     *
     * @param lockKey 鎖的關鍵字,用于在ZooKeeper中創(chuàng)建鎖節(jié)點的路徑。
     * @param lockValue 鎖的值,可以用于進一步標識鎖。
     * @param expire 鎖的過期時間,未使用。
     * @param acquireTimeout 獲取鎖的超時時間。
     * @return 如果成功獲取鎖,返回InterProcessMutex實例;否則返回null。
     */
    @Override
    public InterProcessMutex acquire(String lockKey, String lockValue, long expire, long acquireTimeout) {
        System.out.println("進入了zk的自定義鎖執(zhí)行器");
        // 檢查CuratorFramework實例是否已啟動
        if (!CuratorFrameworkState.STARTED.equals(curatorFramework.getState())) {
            log.warn("instance must be started before calling this method");
            return null;
        }
        // 構建鎖節(jié)點的路徑
        String nodePath = "/curator/lock4j/%s";
        try {
            // 創(chuàng)建InterProcessMutex實例,并嘗試獲取鎖
            InterProcessMutex mutex = new InterProcessMutex(curatorFramework, String.format(nodePath, lockKey));
            final boolean locked = mutex.acquire(acquireTimeout, TimeUnit.MILLISECONDS);
            // 根據(jù)獲取鎖的結果,返回相應的鎖實例或null
            return obtainLockInstance(locked, mutex);
        } catch (Exception e) {
            // 獲取鎖過程中發(fā)生異常,返回null
            return null;
        }
    }
    /**
     * 釋放分布式鎖。
     *
     * @param key 鎖的關鍵字,與獲取鎖時使用的key相同。
     * @param value 鎖的值,與獲取鎖時使用的value相同。
     * @param lockInstance 鎖實例,用于釋放鎖。
     * @return 如果成功釋放鎖,返回true;否則返回false。
     */
    @Override
    public boolean releaseLock(String key, String value, InterProcessMutex lockInstance) {
        System.out.println("進入了zk的自定義鎖執(zhí)行器釋放鎖");
        try {
            // 直接釋放鎖
            lockInstance.release();
        } catch (Exception e) {
            // 釋放鎖過程中發(fā)生異常,記錄日志并返回false
            log.warn("zookeeper lock release error", e);
            return false;
        }
        // 成功釋放鎖,返回true
        return true;
    }
}

添加如下測試接口,在自定義注解中指定executor 為自定義的類即可

//localhost:8082/testZkLock
//@Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 10000, executor = ZookeeperLockExecutor.class)
@Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 10000, executor  = MyZookeeperLockExecutor.class)
@GetMapping("/testZkLock")
public Object testZkLock(){
    long threadId = Thread.currentThread().getId();
    System.out.println(threadId + " : 獲取到了zk的鎖,準備執(zhí)行業(yè)務邏輯");
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return "testLock";
}

啟動工程后,使用接口工具模擬并發(fā)測試

通過控制臺輸出日志可以看到獲取鎖的邏輯走到了自定義的zk執(zhí)行器里面了

4.2.2 基于Redis的自定義執(zhí)行器

同樣,如果要使用基于Redis的自定義執(zhí)行器,也需要首先自定義一個類繼承AbstractLockExecutor抽象類,參考下面的代碼,結合代碼理解

package com.congge.config;
import com.baomidou.lock.executor.AbstractLockExecutor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import java.util.Collections;
/**
 * Redis模板鎖執(zhí)行器,實現(xiàn)基于Redis的分布式鎖,使用StringRedisTemplate和Lua腳本實現(xiàn)鎖的獲取和釋放,提高鎖操作的原子性
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MyRedisTemplateLockExecutor extends AbstractLockExecutor<String> {
    /**
     * 獲取鎖的Lua腳本。
     * 該腳本用于嘗試以NX選項設置鍵值對,實現(xiàn)鎖的獲取。
     */
    private static final RedisScript<String> SCRIPT_LOCK = new DefaultRedisScript<>("return redis.call('set',KEYS[1]," +
            "ARGV[1],'NX','PX',ARGV[2])", String.class);
    /**
     * 釋放鎖的Lua腳本
     * 首先驗證鎖是否由當前持有者釋放,如果是,則刪除鎖
     */
    private static final RedisScript<String> SCRIPT_UNLOCK = new DefaultRedisScript<>(
            "if redis.call('get',KEYS[1]) " +
            "== ARGV[1] then return tostring(redis.call('del', KEYS[1])==1) else return 'false' end",
            String.class);
    /**
     * 表示鎖獲取成功的固定字符串。
     */
    private static final String LOCK_SUCCESS = "OK";
    /**
     * Redis字符串模板,用于執(zhí)行Redis操作。
     */
    private final StringRedisTemplate redisTemplate;
    /**
     * 嘗試獲取鎖
     * 使用Lua腳本在Redis中執(zhí)行SET命令,嘗試獲取鎖
     *
     * @param lockKey        鍵
     * @param lockValue      值,唯一的標識
     * @param expire         鎖的期時間,單位為毫秒
     * @param acquireTimeout 獲取鎖的超時時間,單位為毫秒
     * @return 一個表示鎖實例的字符串,如果獲取鎖失敗,則為null
     */
    @Override
    public String acquire(String lockKey, String lockValue, long expire, long acquireTimeout) {
        System.out.println("嘗試獲取redis的鎖");
        String lock = redisTemplate.execute(SCRIPT_LOCK,
                redisTemplate.getStringSerializer(),
                redisTemplate.getStringSerializer(),
                Collections.singletonList(lockKey),
                lockValue, String.valueOf(expire));
        final boolean locked = LOCK_SUCCESS.equals(lock);
        return obtainLockInstance(locked, lock);
    }
    /**
     * 釋放鎖
     * 使用Lua腳本在Redis中執(zhí)行驗證和刪除操作,以確保只有鎖的持有者才能釋放鎖
     *
     * @param key          鍵
     * @param value        值,用于驗證鎖的所有權。
     * @param lockInstance 表示鎖實例的字符串
     * @return 表示釋放鎖是否成功的布爾值
     */
    @Override
    public boolean releaseLock(String key, String value, String lockInstance) {
        System.out.println("釋放鎖");
        String releaseResult = redisTemplate.execute(SCRIPT_UNLOCK,
                redisTemplate.getStringSerializer(),
                redisTemplate.getStringSerializer(),
                Collections.singletonList(key), value);
        return Boolean.parseBoolean(releaseResult);
    }
}

再添加一個測試接口,如下:

//localhost:8082/testRedisLock
@Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 10000, executor  = MyRedisTemplateLockExecutor.class)
@GetMapping("/testRedisLock")
public Object testRedisLock(){
    long threadId = Thread.currentThread().getId();
    System.out.println(threadId + " : 獲取到了redis的鎖,準備執(zhí)行業(yè)務邏輯");
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return "testLock";
}

使用接口工具模擬一下并發(fā)請求,如下效果

通過控制臺的輸出可以看到自定義的執(zhí)行器生效了

4.3 自定義鎖的key生成策略

默認情況下,如果不做任何的設置,以redis為例,加鎖時生成的key的前綴統(tǒng)一為:lock4j,這個在配置文件中也可以做如下顯示的設置

加鎖過程中,可以看到如下效果,key的格式為 lock4j開頭

某些情況下,如果你想定制自己的key的生成策略,可以通過自定義一個類并實現(xiàn)LockKeyBuilder這個接口,如下:

package com.congge.config;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.lock.LockKeyBuilder;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class DefaultLockKeyBuilder implements LockKeyBuilder {
    private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
    private static final ExpressionParser PARSER = new SpelExpressionParser();
    private BeanResolver beanResolver;
    public DefaultLockKeyBuilder(BeanFactory beanFactory) {
        this.beanResolver = new BeanFactoryResolver(beanFactory);
    }
    public String buildKey(MethodInvocation invocation, String[] definitionKeys) {
        System.out.println("開始構建自定義的key");
        Method method = invocation.getMethod();
        return definitionKeys.length <= 1 && "".equals(definitionKeys[0]) ? "" : this.getSpelDefinitionKey(definitionKeys, method, invocation.getArguments());
    }
    protected String getSpelDefinitionKey(String[] definitionKeys, Method method, Object[] parameterValues) {
        StandardEvaluationContext context = new MethodBasedEvaluationContext((Object)null, method, parameterValues, NAME_DISCOVERER);
        context.setBeanResolver(this.beanResolver);
        List<String> definitionKeyList = new ArrayList(definitionKeys.length);
        String[] var6 = definitionKeys;
        int var7 = definitionKeys.length;
        for(int var8 = 0; var8 < var7; ++var8) {
            String definitionKey = var6[var8];
            if (definitionKey != null && !definitionKey.isEmpty()) {
                String key = (String)PARSER.parseExpression(definitionKey).getValue(context, String.class);
                definitionKeyList.add(key);
            }
        }
        return StringUtils.collectionToDelimitedString(definitionKeyList, ".", "", "");
    }
}

在buildkey的方法里面,你就可以根據(jù)自己的需求自定義key的生成策略了,再次請求接口,可以看到代碼已經(jīng)走到這里了

五、寫在最后

本文詳細介紹了分布式鎖Lock4j的使用,并通過案例代碼演示了其詳細的使用,希望對看到的同學有用哦,本篇到此結束,感謝觀看。

到此這篇關于SpringBoot 整合Lock4j 分布式鎖深度使用案例講解的文章就介紹到這了,更多相關SpringBoot Lock4j 分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • idea構建web項目的超級詳細教程

    idea構建web項目的超級詳細教程

    好多朋友在使用IDEA創(chuàng)建項目時,總會碰到一些小問題,下面這篇文章主要給大家介紹了關于idea構建web項目的超級詳細教程,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • Compare And Swap底層原理及代碼示例詳解

    Compare And Swap底層原理及代碼示例詳解

    這篇文章主要介紹了Compare And Swap底層原理及代碼示例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • Java之CMS和G1垃圾回收過程的異同說明

    Java之CMS和G1垃圾回收過程的異同說明

    CMS垃圾回收器主要基于并發(fā)-清理算法,目的是減少停頓時間,通過四個主要階段進行垃圾回收:初始標記、并發(fā)標記、重新標記和并發(fā)清理,G1垃圾回收器采用標記-整理算法,是JDK9后的默認垃圾收集器,設計為全功能全代收集器
    2024-09-09
  • 項目中SpringBoot配置文件未生效的原因分析與解決方法

    項目中SpringBoot配置文件未生效的原因分析與解決方法

    在日常開發(fā) Spring Boot 項目的時候,大家應該都遇到過這樣一種情況:明明寫了 application.yml,但是項目跑起來之后,配置好像完全沒被加載,下面我們就來聊聊Spring Boot 配置文件未生效 的幾個典型場景與解決方法吧
    2025-09-09
  • Java求一個分數(shù)數(shù)列的前20項之和的實現(xiàn)代碼

    Java求一個分數(shù)數(shù)列的前20項之和的實現(xiàn)代碼

    這篇文章主要介紹了Java求一個分數(shù)數(shù)列的前20項之和的實現(xiàn)代碼,需要的朋友可以參考下
    2017-02-02
  • 詳解Spring Boot 自定義PropertySourceLoader

    詳解Spring Boot 自定義PropertySourceLoader

    這篇文章主要介紹了詳解Spring Boot 自定義PropertySourceLoader,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 使用IDEA反編譯沒有擦除泛型的原因解析

    使用IDEA反編譯沒有擦除泛型的原因解析

    Java泛型引入至今已有近20年,“偽泛型”已被認為是所有開發(fā)者的共識,沒有必要再在反編譯后體現(xiàn)出來反倒大大降低了可讀性,這篇文章主要介紹了使用IDEA反編譯沒有擦除泛型的原因解析,需要的朋友可以參考下
    2023-05-05
  • 麒麟OS?(ARM64)?安裝MySQL、Redis、JDK、Docker超全指南

    麒麟OS?(ARM64)?安裝MySQL、Redis、JDK、Docker超全指南

    麒麟ARM操作系統(tǒng)是國企和政務機關推行信創(chuàng)化選擇率比較高的一款操作系統(tǒng),然而ARM操作系統(tǒng)非主流的X86系統(tǒng),除了命令一樣,在架構方面差別極大,這篇文章主要介紹了麒麟OS?(ARM64)?安裝MySQL、Redis、JDK、Docker的相關資料,需要的朋友可以參考下
    2025-09-09
  • Spring整合Weblogic jms實例詳解

    Spring整合Weblogic jms實例詳解

    這篇文章主要介紹了Spring整合Weblogic jms實例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • SpringBoot結果封裝和異常攔截的實現(xiàn)示例

    SpringBoot結果封裝和異常攔截的實現(xiàn)示例

    SpringBoot 項目中,我們通常需要將結果數(shù)據(jù)封裝成特定的格式,以方便客戶端進行處理,本文主要介紹了SpringBoot?優(yōu)雅的結果封裝和異常攔截,感興趣的可以了解一下
    2023-08-08

最新評論

德州市| 临高县| 缙云县| 屯门区| 镇赉县| 盐池县| 迭部县| 康马县| 宁波市| 富顺县| 绥中县| 常宁市| 黎平县| 马龙县| 普安县| 南宁市| 阜新| 巴林左旗| 文成县| 太仆寺旗| 奎屯市| 西贡区| 久治县| 永平县| 南郑县| 广水市| 辽阳市| 博湖县| 会理县| 孟村| 永清县| 松原市| 北京市| 左权县| 浦东新区| 涿州市| 屏东市| 安图县| 三河市| 托克逊县| 东乡族自治县|