java中的註解使用

二十四桥冷月夜發表於2024-12-09

說明

java中的註解(Annotation)是用於為程式碼新增後設資料的資訊,編譯器可以透過註解進行不同的處理。註解本身並不直接影響程式的執行。

常見內建註解

@Override 標記重寫父類方法
@Deprecated
標記類、方法、欄位等不推薦使用,可能會在未來的版本中刪除。
@SuppressWarnings
抑制編譯器的警告。

自定義註解使用

使用@interface來定義,方法可以有預設值,註解並不直接影響程式碼的語義。

元註解

Java提供了幾個元註解(用於註解其他註解),包括@Target、@Retention、@Documented、@Inherited。
@Target: 指定註解的適用範圍(類、方法、欄位等)。
@Retention: 指定註解的保留策略(原始碼、編譯期或執行時)。
@Documented: 表明註解應該包含在JavaDoc中。
@Inherited: 表示註解可以被子類繼承。

package com.example.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogMask {
    String active();

    String value() default "***";
}

新增aop依賴包

compileOnly("org.springframework.boot:spring-boot-starter-aop:2.6.13")

新增aspect配置類

package com.example.config;

import com.example.annotation.LogMask;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Slf4j
@Aspect
@Component
public class LogAspect {


    @Before(value = "@annotation(logMask)", argNames = "joinPoint,logMask")
    public void logBefore(final JoinPoint joinPoint, final LogMask logMask) {
        log.info("action:[{}]", logMask.action());
        System.out.println("Method " + joinPoint.getSignature().getName() + " is starting...");

    }

    // 在方法執行後執行
    @After(value = "@annotation(com.example.annotation.LogMask)")
    public void logAfter(final JoinPoint joinPoint) {
        System.out.println("Method " + joinPoint.getSignature().getName() + " has finished.");
    }

    // 環繞通知(可以在方法執行前後做更多操作,返回值可以控制方法是否執行)
    @Around(value = "@annotation(logMask)", argNames = "joinPoint,logMask")
    public Object logAround(final ProceedingJoinPoint joinPoint, LogMask logMask) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();  // 執行目標方法
        long endTime = System.currentTimeMillis();
        System.out.println("Method " + joinPoint.getSignature().getName() + " executed in " + (endTime - startTime) + " ms");
        return result;
    }

}

在方法上新增自定義註解

package com.example.service;


import com.example.annotation.LogMask;
import org.springframework.stereotype.Service;

@Service
public class LoginService {

    @LogMask(action = "login")
    public String login(String username, String password) {
        System.out.println("username login success:" + username);
        return "success";
    }
}

JoinPoint 和 ProceedingJoinPoint的區別

JoinPoint

  1. 用在 @Before 和 @After 通知上
  2. 只能獲取方法資訊。
  3. 不能控制目標方法的執行(不能呼叫 proceed())。
  4. 適用於 @Before、@After 等不需要改變方法行為的通知,即不能改變方法的引數值那些,方法的執行過程不受改變

ProceedingJoinPoint

  1. ProceedingJoinPoint 是 JoinPoint 的子介面
  2. 主要用於 @Around 通知中。它除了擁有 JoinPoint 的功能外
  3. 提供了 proceed() 方法,允許在通知中控制目標方法的執行

相關文章