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

基于SpringBoot+AOP實(shí)現(xiàn)操作日志記錄

 更新時(shí)間:2026年04月17日 08:35:14   作者:希望永不加班  
本文介紹了使用日志記錄的實(shí)現(xiàn)方法,步驟包括明確記錄信息、搭建基礎(chǔ)環(huán)境、創(chuàng)建操作日志實(shí)體類和自定義注解、創(chuàng)建AOP切面,重點(diǎn)在于精準(zhǔn)控制需要記錄日志的接口,通過自定義注解和使用、切點(diǎn)表達(dá)式、環(huán)繞通知實(shí)現(xiàn)實(shí)現(xiàn)日志記錄邏輯,需要的朋友可以參考下

今天就來講講Spring AOP最實(shí)用的實(shí)戰(zhàn)場(chǎng)景——用 SpringBoot + AOP 實(shí)現(xiàn)操作日志記錄

操作日志是項(xiàng)目必備功能:比如用戶登錄、接口調(diào)用、數(shù)據(jù)新增/修改/刪除,都需要記錄操作人、操作時(shí)間、操作內(nèi)容、接口地址等信息,方便后續(xù)排查問題、審計(jì)追溯。

一、明確操作日志要記錄哪些信息?

先梳理操作日志的核心字段,避免后續(xù)代碼遺漏,實(shí)戰(zhàn)中可根據(jù)項(xiàng)目需求增減,這里給出通用模板:

  • 操作人:當(dāng)前登錄用戶的用戶名/ID(實(shí)戰(zhàn)中結(jié)合 Spring Security 或 Token 獲?。?;
  • 操作時(shí)間:接口執(zhí)行的時(shí)間(精確到毫秒);
  • 操作模塊:比如“用戶管理”“訂單管理”“商品管理”(標(biāo)記當(dāng)前操作屬于哪個(gè)模塊);
  • 操作描述:比如“新增用戶”“刪除訂單”“查詢商品列表”(清晰說明操作內(nèi)容);
  • 接口地址:被調(diào)用的接口 URL(比如 /api/user/add);
  • 請(qǐng)求方式:GET/POST/PUT/DELETE;
  • 請(qǐng)求參數(shù):接口接收的參數(shù)(JSON 格式);
  • 返回結(jié)果:接口返回的數(shù)據(jù)(JSON 格式);
  • 執(zhí)行狀態(tài):成功/失敗;
  • 異常信息:如果接口執(zhí)行失敗,記錄異常詳情(便于排查);
  • 操作 IP:調(diào)用接口的客戶端 IP 地址。

二、從零實(shí)現(xiàn) AOP 操作日志

步驟1:搭建基礎(chǔ)環(huán)境(導(dǎo)入依賴)

SpringBoot 項(xiàng)目中,實(shí)現(xiàn) AOP 只需導(dǎo)入 spring-boot-starter-aop 依賴,無需額外導(dǎo)入其他包,在 pom.xml 中添加:

<!-- Spring AOP 依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 工具包:用于 JSON 格式化、IP 地址獲?。蛇x,簡(jiǎn)化代碼) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.32</version>
</dependency>
<!-- 用于獲取客戶端 IP(可選,也可自己寫工具類) -->
<dependency>
    <groupId>eu.bitwalker</groupId>
    <artifactId>UserAgentUtils</artifactId>
    <version>1.21</version>
</dependency>

說明:fastjson2 用于將請(qǐng)求參數(shù)、返回結(jié)果轉(zhuǎn)為 JSON 字符串;UserAgentUtils 用于獲取客戶端 IP 和瀏覽器信息,可根據(jù)需求選擇是否導(dǎo)入。

步驟2:創(chuàng)建操作日志實(shí)體類(存儲(chǔ)日志數(shù)據(jù))

創(chuàng)建實(shí)體類 OperationLog,對(duì)應(yīng)操作日志的核心字段,后續(xù)可直接映射到數(shù)據(jù)庫(kù)(這里省略數(shù)據(jù)庫(kù)操作,重點(diǎn)放在 AOP 實(shí)現(xiàn)):

import lombok.Data;
import java.time.LocalDateTime;
/**
 * 操作日志實(shí)體類
 */
@Data
public class OperationLog {
    // 主鍵(實(shí)戰(zhàn)中可自增)
    private Long id;
    // 操作人(用戶名/ID)
    private String operator;
    // 操作時(shí)間
    private LocalDateTime operationTime;
    // 操作模塊
    private String module;
    // 操作描述
    private String description;
    // 接口地址
    private String requestUrl;
    // 請(qǐng)求方式
    private String requestMethod;
    // 請(qǐng)求參數(shù)(JSON 格式)
    private String requestParams;
    // 返回結(jié)果(JSON 格式)
    private String responseResult;
    // 執(zhí)行狀態(tài)(0-失敗,1-成功)
    private Integer status;
    // 異常信息(失敗時(shí)填寫)
    private String errorMsg;
    // 操作 IP
    private String operationIp;
}

說明:用 @Data 注解(lombok)簡(jiǎn)化 getter/setter 方法,實(shí)戰(zhàn)中需導(dǎo)入 lombok 依賴(如果未導(dǎo)入)。

步驟3:創(chuàng)建自定義注解(精準(zhǔn)定位需要記錄日志的接口)

我們用「自定義注解」來標(biāo)記需要記錄操作日志的接口,這樣可以靈活控制哪些接口需要記錄日志,哪些不需要——比直接用切點(diǎn)表達(dá)式匹配包/類更靈活。

import java.lang.annotation.*;
/**
 * 自定義操作日志注解
 * @Target:注解作用范圍(METHOD:作用在方法上)
 * @Retention:注解保留時(shí)機(jī)(RUNTIME:運(yùn)行時(shí)保留,AOP 可獲取)
 * @Documented:生成文檔時(shí)包含該注解
 */
@Target(ElementType.METHOD) // 只作用于方法
@Retention(RetentionPolicy.RUNTIME) // 運(yùn)行時(shí)生效
@Documented
public @interface OperationLogAnnotation {
    // 操作模塊(必填,比如“用戶管理”)
    String module() default "";
    // 操作描述(必填,比如“新增用戶”)
    String description() default "";
}

說明:該注解有兩個(gè)屬性,module(操作模塊)和 description(操作描述),在需要記錄日志的接口方法上添加該注解,并填寫對(duì)應(yīng)屬性即可。

步驟4:創(chuàng)建 AOP 切面(實(shí)現(xiàn)日志記錄)

這是本次實(shí)戰(zhàn)的核心,創(chuàng)建切面類,定義切點(diǎn)(匹配帶有 @OperationLogAnnotation 注解的方法)、通知(環(huán)繞通知,實(shí)現(xiàn)日志記錄邏輯),完成日志的收集和處理。

import com.alibaba.fastjson2.JSON;
import eu.bitwalker.useragentutils.UserAgent;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
/**
 * 操作日志切面類
 * @Aspect:標(biāo)記此類為切面
 * @Component:交給 Spring 管理,讓 Spring 掃描到該切面
 */
@Aspect
@Component
public class OperationLogAspect {
    // 1. 定義切點(diǎn):匹配帶有 @OperationLogAnnotation 注解的方法
    @Pointcut("@annotation(com.example.demo.annotation.OperationLogAnnotation)")
    public void operationLogPointcut() {} // 切點(diǎn)方法,無實(shí)際邏輯,僅用于標(biāo)記
    // 2. 定義環(huán)繞通知:包裹切點(diǎn)方法,可在方法執(zhí)行前、執(zhí)行后、異常時(shí)處理
    @Around("operationLogPointcut()")
    public Object recordOperationLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. 初始化操作日志對(duì)象
        OperationLog operationLog = new OperationLog();
        // 2. 獲取當(dāng)前請(qǐng)求對(duì)象,用于獲取請(qǐng)求信息(URL、請(qǐng)求方式、IP 等)
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 3. 填充日志基礎(chǔ)信息(無論接口成功/失敗,都需要記錄)
        // 3.1 獲取操作人(實(shí)戰(zhàn)中需結(jié)合 Spring Security/Token 獲取,這里模擬 admin)
        operationLog.setOperator("admin");
        // 3.2 操作時(shí)間(當(dāng)前時(shí)間)
        operationLog.setOperationTime(LocalDateTime.now());
        // 3.3 接口地址
        operationLog.setRequestUrl(request.getRequestURI());
        // 3.4 請(qǐng)求方式(GET/POST)
        operationLog.setRequestMethod(request.getMethod());
        // 3.5 操作 IP(獲取客戶端真實(shí) IP)
        operationLog.setOperationIp(getClientIp(request));
        // 3.6 請(qǐng)求參數(shù)(將方法參數(shù)轉(zhuǎn)為 JSON 字符串)
        Object[] args = joinPoint.getArgs();
        operationLog.setRequestParams(JSON.toJSONString(args));
        // 4. 獲取自定義注解的屬性(模塊、描述)
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);
        operationLog.setModule(annotation.module());
        operationLog.setDescription(annotation.description());
        // 5. 執(zhí)行目標(biāo)方法(核心業(yè)務(wù)邏輯),捕獲執(zhí)行結(jié)果和異常
        Object result = null;
        try {
            // 執(zhí)行目標(biāo)方法(比如接口的核心邏輯)
            result = joinPoint.proceed();
            // 方法執(zhí)行成功:設(shè)置狀態(tài)為 1(成功),記錄返回結(jié)果
            operationLog.setStatus(1);
            operationLog.setResponseResult(JSON.toJSONString(result));
        } catch (Throwable throwable) {
            // 方法執(zhí)行失敗:設(shè)置狀態(tài)為 0(失?。涗洰惓P畔?
            operationLog.setStatus(0);
            operationLog.setErrorMsg(throwable.getMessage());
            // 拋出異常,不影響原有業(yè)務(wù)邏輯的異常處理
            throw throwable;
        } finally {
            // 6. 日志持久化(實(shí)戰(zhàn)中可存入數(shù)據(jù)庫(kù)、ElasticSearch 等,這里模擬打?。?
            System.out.println("操作日志記錄:" + JSON.toJSONString(operationLog, true));
            // TODO: 實(shí)戰(zhàn)中替換為數(shù)據(jù)庫(kù)插入操作(比如調(diào)用 OperationLogService.save(operationLog))
        }
        // 返回目標(biāo)方法的執(zhí)行結(jié)果,不影響原有接口的返回值
        return result;
    }
    /**
     * 工具方法:獲取客戶端真實(shí) IP(處理代理場(chǎng)景,比如 Nginx 代理)
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 處理多代理場(chǎng)景,取第一個(gè)非 unknown 的 IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}

核心解讀:

  • 切點(diǎn):通過 @annotation 匹配帶有自定義注解的方法,精準(zhǔn)控制需要記錄日志的接口;
  • 環(huán)繞通知:用 @Around 包裹目標(biāo)方法,先收集請(qǐng)求信息、注解屬性,再執(zhí)行目標(biāo)方法,最后處理日志(成功/失敗);
  • IP 獲取:處理了 Nginx 代理等場(chǎng)景,確保獲取到客戶端真實(shí) IP;
  • 異常處理:捕獲目標(biāo)方法的異常,記錄異常信息,同時(shí)重新拋出異常,不影響原有業(yè)務(wù)的異常處理邏輯;
  • 日志持久化:這里用打印模擬,實(shí)戰(zhàn)中需替換為數(shù)據(jù)庫(kù)插入、ES 存儲(chǔ)等邏輯。

步驟5:接口測(cè)試(驗(yàn)證日志記錄效果)

創(chuàng)建一個(gè)測(cè)試接口,添加自定義 @OperationLogAnnotation 注解,啟動(dòng)項(xiàng)目,調(diào)用接口,查看日志是否正常記錄。

import com.example.demo.annotation.OperationLogAnnotation;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
 * 測(cè)試接口:用戶管理模塊
 */
@RestController
@RequestMapping("/api/user")
public class UserController {
    // 添加 @OperationLogAnnotation 注解,標(biāo)記需要記錄日志
    @OperationLogAnnotation(module = "用戶管理", description = "新增用戶")
    @PostMapping("/add")
    public Map<String, Object> addUser(@RequestBody Map<String, String> params) {
        // 模擬新增用戶核心邏輯
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "新增用戶成功");
        result.put("data", params);
        return result;
    }
    // 測(cè)試異常場(chǎng)景
    @OperationLogAnnotation(module = "用戶管理", description = "刪除用戶")
    @DeleteMapping("/delete/{id}")
    public Map<String, Object> deleteUser(@PathVariable Long id) {
        // 模擬異常(比如刪除不存在的用戶)
        if (id <= 0) {
            throw new RuntimeException("用戶ID非法,無法刪除");
        }
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "刪除用戶成功");
        return result;
    }
}

測(cè)試1:調(diào)用新增用戶接口

請(qǐng)求地址:http://localhost:8080/api/user/add
請(qǐng)求方式:POST
請(qǐng)求參數(shù):{"username":"test","password":"123456"}

控制臺(tái)打印的日志(格式化后):

操作日志記錄:{
    "description":"新增用戶",
    "module":"用戶管理",
    "operationIp":"127.0.0.1",
    "operationTime":"2026-04-14T15:30:00",
    "operator":"admin",
    "requestMethod":"POST",
    "requestParams":"[{\"password\":\"123456\",\"username\":\"test\"}]",
    "requestUrl":"/api/user/add",
    "responseResult":"{\"code\":200,\"data\":{\"password\":\"123456\",\"username\":\"test\"},\"msg\":\"新增用戶成功\"}",
    "status":1
}

測(cè)試2:調(diào)用刪除用戶接口

請(qǐng)求地址:http://localhost:8080/api/user/delete/-1
請(qǐng)求方式:DELETE

控制臺(tái)打印的日志(格式化后):

操作日志記錄:{
    "description":"刪除用戶",
    "errorMsg":"用戶ID非法,無法刪除",
    "module":"用戶管理",
    "operationIp":"127.0.0.1",
    "operationTime":"2026-04-14T15:35:00",
    "operator":"admin",
    "requestMethod":"DELETE",
    "requestParams":"[-1]",
    "requestUrl":"/api/user/delete/-1",
    "responseResult":"null",
    "status":0
}

驗(yàn)證結(jié)果:兩種場(chǎng)景的日志都正常記錄,包含了所有核心字段,符合預(yù)期!

三、優(yōu)化技巧

上面的基礎(chǔ)實(shí)現(xiàn)已經(jīng)能滿足大部分項(xiàng)目需求,下面補(bǔ)充3個(gè)實(shí)戰(zhàn)常用的優(yōu)化點(diǎn),讓日志功能更完善。

優(yōu)化1:獲取真實(shí)操作人(替換模擬值)

實(shí)戰(zhàn)中,操作人不能用模擬的“admin”,需結(jié)合 Spring Security 或 Token 解析獲取當(dāng)前登錄用戶:

// 結(jié)合 Spring Security 獲取當(dāng)前登錄用戶
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && !(authentication.getPrincipal() instanceof String)) {
    UserDetails userDetails = (UserDetails) authentication.getPrincipal();
    operationLog.setOperator(userDetails.getUsername()); // 獲取用戶名
}

優(yōu)化2:日志持久化(存入數(shù)據(jù)庫(kù))

創(chuàng)建 OperationLogService 和 OperationLogMapper,將日志對(duì)象存入數(shù)據(jù)庫(kù)(以 MyBatis-Plus 為例):

// 1. 注入 OperationLogService
@Autowired
private OperationLogService operationLogService;
// 2. 在 finally 中替換打印邏輯,改為存入數(shù)據(jù)庫(kù)
finally {
    operationLogService.save(operationLog); // MyBatis-Plus 自帶的保存方法
}

優(yōu)化3:忽略敏感參數(shù)(避免日志泄露)

接口參數(shù)中可能包含密碼、手機(jī)號(hào)等敏感信息,需要忽略這些參數(shù),避免日志泄露,可自定義注解+攔截處理:

// 1. 自定義忽略敏感參數(shù)注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreSensitive {
}
// 2. 在實(shí)體類敏感字段上添加注解
@Data
public class User {
    private Long id;
    private String username;
    @IgnoreSensitive // 忽略密碼字段
    private String password;
}
// 3. 在切面中,處理敏感參數(shù)(替換為 ****)
// (核心邏輯:反射獲取字段,判斷是否有 @IgnoreSensitive 注解,有則替換值)

四、注意事項(xiàng)

切面類忘記加 @Component 注解

? 錯(cuò)誤做法:只加 @Aspect 標(biāo)記切面,忘記加 @Component;
? 正確做法:@Aspect 只是標(biāo)記切面,必須加 @Component 交給 Spring 管理,否則 Spring 無法掃描到切面,日志記錄失效。

環(huán)繞通知中忘記調(diào)用 joinPoint.proceed()

? 錯(cuò)誤做法:只收集日志,不執(zhí)行目標(biāo)方法,導(dǎo)致接口無法正常返回;
? 正確做法:必須調(diào)用 joinPoint.proceed() 執(zhí)行目標(biāo)方法,同時(shí)接收返回結(jié)果,否則核心業(yè)務(wù)邏輯無法執(zhí)行。

請(qǐng)求參數(shù)為 MultipartFile(文件上傳)時(shí),JSON 格式化報(bào)錯(cuò)

? 錯(cuò)誤表現(xiàn):文件上傳接口,日志記錄時(shí),JSON.toJSONString(args) 報(bào)錯(cuò);
? 解決方案:判斷參數(shù)類型,如果是 MultipartFile,不進(jìn)行 JSON 格式化,直接標(biāo)記為“文件上傳”。

文末小結(jié)

用 SpringBoot + AOP 實(shí)現(xiàn)操作日志,核心就是“自定義注解標(biāo)記接口 + 切面收集日志信息 + 環(huán)繞通知處理增強(qiáng)”,全程無侵入式編碼,復(fù)用性極高。

記?。篈OP 的核心是“解耦”,把日志這種通用功能,和核心業(yè)務(wù)邏輯分離,既保證了核心代碼的簡(jiǎn)潔,又方便后續(xù)維護(hù)和擴(kuò)展。

以上就是基于SpringBoot+AOP實(shí)現(xiàn)操作日志記錄的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot AOP日志記錄的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法

    SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法

    這篇文章主要介紹了SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java多線程讀寫鎖ReentrantReadWriteLock類詳解

    Java多線程讀寫鎖ReentrantReadWriteLock類詳解

    本文詳細(xì)講解了Java多線程讀寫鎖ReentrantReadWriteLock類,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • Java實(shí)現(xiàn)五子棋AI算法

    Java實(shí)現(xiàn)五子棋AI算法

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)五子棋AI算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • SpringBoot結(jié)合WebSocket實(shí)現(xiàn)聊天功能

    SpringBoot結(jié)合WebSocket實(shí)現(xiàn)聊天功能

    本文介紹了如何使用SpringBoot和WebSocket實(shí)現(xiàn)一個(gè)簡(jiǎn)單的聊天功能,包括導(dǎo)入依賴、配置類、創(chuàng)建消息實(shí)體、指定ServerEndpoint、創(chuàng)建客戶端等步驟,通過具體示例,演示了如何發(fā)送個(gè)人消息和群發(fā)消息,實(shí)現(xiàn)了基本的聊天功能,適合需要在項(xiàng)目中實(shí)現(xiàn)實(shí)時(shí)通訊功能的開發(fā)者參考
    2024-11-11
  • Spring Boot 集成 Solr 的詳細(xì)示例

    Spring Boot 集成 Solr 的詳細(xì)示例

    這篇文章主要介紹了Spring Boot 集成 Solr 的詳細(xì)示例,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-05-05
  • Java8 接口默認(rèn)方法和靜態(tài)方法

    Java8 接口默認(rèn)方法和靜態(tài)方法

    這篇文章主要介紹了Java8 接口默認(rèn)方法和靜態(tài)方法,在默認(rèn)接口中使用關(guān)鍵字default聲明并提供具體實(shí)現(xiàn),而且該方法不需要添加public關(guān)鍵字就可以公開調(diào)用,甚至你可以在其實(shí)現(xiàn)類中覆寫,帶著對(duì)默認(rèn)接口的方法和小編一起探索下面文章內(nèi)容的靜態(tài)方法吧
    2021-10-10
  • JAVA DOM解析XML文件過程詳解

    JAVA DOM解析XML文件過程詳解

    這篇文章主要介紹了JAVA DOM解析XML文件過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Java集成presto查詢方式

    Java集成presto查詢方式

    這篇文章主要介紹了Java集成presto查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java toString方法重寫工具之ToStringBuilder案例詳解

    Java toString方法重寫工具之ToStringBuilder案例詳解

    這篇文章主要介紹了Java toString方法重寫工具之ToStringBuilder案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼

    Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼

    這篇文章主要介紹了Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02

最新評(píng)論

永平县| 博兴县| 长子县| 玉林市| 临城县| 新田县| 游戏| 垣曲县| 海门市| 婺源县| 黄平县| 蓬安县| 垦利县| 石景山区| 四子王旗| 娱乐| 宜兰县| 崇阳县| 宜黄县| 股票| 左贡县| 山丹县| 克什克腾旗| 汤阴县| 塘沽区| 江川县| 营山县| 徐水县| 稻城县| 铅山县| 喀什市| 龙口市| 合山市| 乐平市| 合阳县| 和林格尔县| 大冶市| 肇源县| 霍林郭勒市| 霍城县| 包头市|