JAVA自定義注解使用指南
什么是注解?
注解是一種特殊的接口,用于為Java代碼提供元數(shù)據(jù)。它們不會直接影響代碼的執(zhí)行,但可以被編譯器、開發(fā)工具或運(yùn)行時環(huán)境讀取和使用。
Java內(nèi)置了一些常用的注解,如:
@Override - 表示方法重寫父類方法
@Deprecated - 表示代碼已過時
@SuppressWarnings - 抑制編譯器警告
注解的基本語法
定義注解
使用@interface關(guān)鍵字來定義注解:
public @interface AutoFill {
}元注解
元注解是用來注解其他注解的注解,Java提供了以下幾種元注解:
@Target - 指定注解可以應(yīng)用的目標(biāo)元素類型
@Retention - 指定注解的保留策略
@Documented - 表示注解應(yīng)該被包含在Javadoc中
@Inherited - 表示注解可以被繼承
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
/**
* 數(shù)據(jù)庫操作類型:INSERT、UPDATE
*/
OperationType value();
}示例代碼展示了一個用于公共字段自動填充的自定義注解,@Target明確注解可在方法上使用,@Retention明確在程序運(yùn)行時可見。
注解元素
注解中可以定義元素,這些元素可以有默認(rèn)值:
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}示例自定義注解中的value方法則用來返回上示枚舉類型數(shù)據(jù),明確 使用該注解的方法 的作用,使用方式如下:
/**
* 更新員工信息
* @param employee
*/
@AutoFill(OperationType.UPDATE)
void updateById(Employee employee);當(dāng)注解只有一個方法且方法名為 value 時,使用時可以省略方法名,如果方法不叫 value,就必須明確指定方法名:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
/**
* 數(shù)據(jù)庫操作類型:INSERT、UPDATE
*/
OperationType type();
}/**
* 更新員工信息
* @param employee
*/
@AutoFill(type = OperationType.UPDATE)
void updateById(Employee employee);自定義注解的使用
通過反射處理注解
我們可以使用反射機(jī)制在運(yùn)行時讀取和處理注解:
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 公共字段自動填充切入點(diǎn)
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut() {}
/**
* 公共字段自動填充
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint) throws Throwable {
log.info("公共字段自動填充通知開始");
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
AutoFill autoFill= signature.getMethod().getAnnotation(AutoFill.class);
// 獲取數(shù)據(jù)庫操作類型
Enum operationType = autoFill.value();
// 從ThreadLocal中獲取當(dāng)前登錄用戶的id
Long currentId = BaseContext.getCurrentId();
// 獲取當(dāng)前時間
LocalDateTime now = LocalDateTime.now();
// 從joinPoint中獲取參數(shù)
Object[] args = joinPoint.getArgs();
if(args==null || args.length==0){
return;
}
// 從參數(shù)中獲取實(shí)體對象
Object entity = args[0];
// 調(diào)用實(shí)體對象的方法,設(shè)置創(chuàng)建時間、創(chuàng)建人、更新時間、更新人
if(operationType==OperationType.INSERT){
try{
Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
setCreateTime.invoke(entity, now);
setUpdateTime.invoke(entity, now);
setCreateUser.invoke(entity, currentId);
setUpdateUser.invoke(entity, currentId);
}catch (Exception e){
log.error("公共字段自動填充通知異常", e);
}
}else if(operationType==OperationType.UPDATE){
try{
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
setUpdateTime.invoke(entity, now);
setUpdateUser.invoke(entity, currentId);
}catch (Exception e){
log.error("公共字段自動填充通知異常", e);
}
}
}
}上述示例展示的是@AutoFill注解進(jìn)行公共字段自動填充必要的切面類。
@Aspect
該注解用于聲明切面類。
/**
* 公共字段自動填充切入點(diǎn)
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut() {}這一部分用于聲明哪些部分需要攔截。(在com.sky.mapper包下的所有類及其所有方法 且 被自定義注解(@AutoFill)所標(biāo)注)
/**
* 公共字段自動填充
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint) throws Throwable@Before: 表示這是一個前置通知,在目標(biāo)方法執(zhí)行之前運(yùn)行。
autoFillPointCut(): 引用一個切點(diǎn)表達(dá)式,定義了哪些方法需要被攔截。
JoinPoint: AOP 連接點(diǎn)對象,可以獲取被攔截方法的詳細(xì)信息:方法名、參數(shù)、目標(biāo)對象等。通過 joinPoint.getArgs() 獲取方法參數(shù)。
MethodSignature signature = (MethodSignature)joinPoint.getSignature(); AutoFill autoFill= signature.getMethod().getAnnotation(AutoFill.class); // 獲取數(shù)據(jù)庫操作類型 Enum operationType = autoFill.value();
joinPoint.getSignature(): 獲取連接點(diǎn)的簽名信息。
(MethodSignature): 強(qiáng)制轉(zhuǎn)換為 MethodSignature 類型,因?yàn)?nbsp;Spring AOP 只攔截方法。
signature.getMethod(): 獲取被攔截的 Method 對象。
.getAnnotation(AutoFill.class): 從方法上獲取 @AutoFill 注解。
autoFill.value(): 調(diào)用注解的 value() 方法,獲取注解中定義的枚舉值。
// 從joinPoint中獲取參數(shù)
Object[] args = joinPoint.getArgs();
if(args==null || args.length==0){
return;
}
// 從參數(shù)中獲取實(shí)體對象
Object entity = args[0];利用從joinPoint中獲取的參數(shù)獲得原本方法中傳遞的實(shí)體對象。
Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);
setCreateTime.invoke(entity, now);
setCreateUser.invoke(entity, currentId);利用反射為對象設(shè)置公共字段。
最終效果





@AutoFill注解能有效替代原本冗長且重復(fù)的公共字段設(shè)置代碼。
到此這篇關(guān)于JAVA自定義注解全解的文章就介紹到這了,更多相關(guān)java自定義注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot項(xiàng)目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決)
這篇文章主要介紹了SpringBoot項(xiàng)目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
spring Security配置攔截規(guī)則小結(jié)
本文介紹了使用Spring Security解決后臺管理系統(tǒng)在訪問靜態(tài)資源如圖片時需要登錄驗(yàn)證的問題,通過配置攔截規(guī)則,將靜態(tài)資源路徑添加到白名單,感興趣的可以了解一下2025-09-09
Springboot整合RabbitMq測試TTL的方法詳解
這篇文章主要介紹了Springboot整合RabbitMq測試TTL的設(shè)置,設(shè)置TTL一般由兩種設(shè)置方法,設(shè)置整個隊列的過期時間另一種設(shè)置單個消息的過期時間,通過示例圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03
JAVA 并發(fā)容器的一些易出錯點(diǎn)你知道嗎
今天給大家?guī)淼奈恼率荍ava并發(fā)編程的相關(guān)知識,文中對java同步容器與并發(fā)容器做了非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-09-09

