java如何自定義注解
注解是一種能被添加到j(luò)ava源代碼中的元數(shù)據(jù),方法、類、參數(shù)和包都可以用注解來修飾。
注解可以看作是一種特殊的標(biāo)記,可以用在方法、類、參數(shù)和包上,程序在編譯或者運行時可以檢測到這些標(biāo)記而進(jìn)行一些特殊的處理。
聲明一個注解要用到的東西
- 修飾符:訪問修飾符必須為public,不寫默認(rèn)為pubic
- 關(guān)鍵字:關(guān)鍵字為@interface
- 注解名稱:注解名稱為自定義注解的名稱,使用時還會用到
- 注解類型元素:注解類型元素是注解中內(nèi)容
其次,JDK中還有一些元注解,這些元注解可以用來修飾注解。
主要有:@Target,@Retention,@Document,@Inherited。
@Target
作用:
用于描述注解的使用范圍(即:被描述的注解可以用在什么地方)。
取值有:

@Retention
作用:
表示需要在什么級別保存該注釋信息,用于描述注解的生命周期(即:被描述的注解在什么范圍內(nèi)有效)
即:注解的生命周期。

@Document
作用:
表明該注解標(biāo)記的元素可以被Javadoc 或類似的工具文檔化
@Inherited
作用:
表明使用了@Inherited注解的注解,所標(biāo)記的類的子類也會擁有這個注解。
自定義注解中參數(shù)可支持的數(shù)據(jù)類型:
1.八大基本數(shù)據(jù)類型
2.String類型
3.Class類型
4.enum類型
5.Annotation類型
6.以上所有類型的數(shù)組
自定義一個注解,如下所示:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
String username() default "";
OperationType type();
String content() default "";
}通過AOP加自定義注解簡單實現(xiàn)一個操作日志的記錄
自定義注解類:
package com.redistext.log;
import java.lang.annotation.*;
/**
* @author: maorui
* @description: TODO
* @date: 2021/10/27 21:23
* @description: V1.0
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
String username() default "admin";
String type(); //記錄操作類型
String content() default ""; //記錄操作內(nèi)容
}切面類:
package com.redistext.log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @author: maorui
* @description: TODO
* @date: 2021/10/27 21:29
* @description: V1.0
*/
@Aspect
@Component("logAspect")
public class LogAspect {
// 配置織入點
@Pointcut("@annotation(OperationLog)")
public void logPointCut() {
}
/**
* 前置通知 用于攔截操作,在方法返回后執(zhí)行
*
* @param joinPoint 切點
*/
@AfterReturning(pointcut = "logPointCut()")
public void doBefore(JoinPoint joinPoint) {
handleLog(joinPoint, null);
}
/**
* 攔截異常操作,有異常時執(zhí)行
*
* @param joinPoint
* @param e
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfter(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e);
}
private void handleLog(JoinPoint joinPoint, Exception e){
try {
// 得到注解
OperationLog operationLog = getAnnotationLog(joinPoint);
System.out.println("---------------自定義注解:" + operationLog);
if (operationLog == null) {
return;
}
// 得到方法名稱
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
String type = operationLog.type();
String content = operationLog.content();
String username = operationLog.username();
// 打印日志
System.out.println("操作類型:" + type);
System.out.println("操作名稱:" + content);
System.out.println("操作人員:" + username);
System.out.println("類名:" + className);
System.out.println("方法名:" + methodName);
} catch (Exception e1) {
System.out.println("======前置通知異常======");
e1.printStackTrace();
}
}
private static OperationLog getAnnotationLog(JoinPoint joinPoint) throws Exception{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
// 拿到自定義注解中的信息
return method.getAnnotation(OperationLog.class);
}
return null;
}
}測試類:
package com.redistext.log;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: maorui
* @description: TODO
* @date: 2021/10/27 21:40
* @description: V1.0
*/
@RestController
@RequestMapping("/operationLog")
public class OperationLogController {
@OperationLog(type = "add", content = "添加")
@GetMapping(value = "/add")
public String addOperation(){
return "add";
}
@OperationLog(type = "update", username = "adminFather")
@GetMapping(value = "/update")
public String updateOperation(){
return "update";
}
@OperationLog(type = "delete", content = "刪除", username = "adminMother")
@GetMapping(value = "/delete")
public String deleteOperation(){
return "delete";
}
@OperationLog(type = "find")
@GetMapping(value = "/find")
public String findOperation(){
return "find";
}
}依次調(diào)用測試類各個接口,記錄的操作日志信息如下:

總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot實現(xiàn)自定義Redis的連接的流程步驟
Spring Boot 自定義 Redis 主要是指在基于 Spring Boot 的應(yīng)用程序中,當(dāng)你需要更深入地控制或擴(kuò)展對 Redis 數(shù)據(jù)庫的操作,而不是僅僅依賴 Spring Data Redis 的默認(rèn)配置,本文給大家介紹了SpringBoot實現(xiàn)自定義Redis的連接的流程步驟,需要的朋友可以參考下2024-09-09
解決@Autowired注入空指針問題(利用Bean的生命周期)
這篇文章主要介紹了解決@Autowired注入空指針問題(利用Bean的生命周期),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
Java基礎(chǔ)知識之StringReader流的使用
這篇文章主要介紹了Java基礎(chǔ)知識之StringReader流的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
IDEA JeeSite框架httpSession.invalidate()無效問題解決方案
這篇文章主要介紹了IDEA JeeSite框架httpSession.invalidate()無效問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09
SpringBoot啟動流程之引導(dǎo)上下文DefaultBootstrapContext的過程
本文詳細(xì)介紹了SpringBoot版本2.7.18中SpringApplication的run方法,引導(dǎo)注冊組件初始化器BootstrapRegistryInitializer是SpringBoot的第一個擴(kuò)展點,負(fù)責(zé)應(yīng)用啟動早期階段的初始化和配置,感興趣的朋友跟隨小編一起看看吧2024-11-11

