Spring開發(fā)中自定義注解的使用詳解
Spring自定義注解
在Java項(xiàng)目中,可以自定義注解,方便進(jìn)行某些處理操作,提供開發(fā)效率。
比如,在進(jìn)行實(shí)體類的crud操作時(shí),一般都有create_time, createUser, updateTime, updateUser這幾個(gè)字段,而且不是核心業(yè)務(wù)代碼,這時(shí)可以引入注解簡(jiǎn)化開發(fā)和提高效率。
比如下面這段代碼:
//實(shí)體類的新增操作
public void save(CategoryDTO categoryDTO) {
//....................................
//設(shè)置創(chuàng)建時(shí)間、修改時(shí)間、創(chuàng)建人、修改人
category.setCreateTime(LocalDateTime.now());
category.setUpdateTime(LocalDateTime.now());
category.setCreateUser(BaseContext.getCurrentId());
category.setUpdateUser(BaseContext.getCurrentId());
categoryMapper.insert(category);
}如果都按照上述的操作方式來處理這些公共字段, 需要在每一個(gè)業(yè)務(wù)方法中進(jìn)行操作, 編碼相對(duì)冗余、繁瑣,那能不能對(duì)于這些公共字段在某個(gè)地方統(tǒng)一處理,來簡(jiǎn)化開發(fā)呢?
以下以自定義注解AutoFill為例,使用AOP切面編程,實(shí)現(xiàn)功能增強(qiáng),來完成公共字段自動(dòng)填充功能。 說明如何自定義注解,和使用注解
實(shí)現(xiàn)步驟:
- 自定義注解 AutoFill,用于標(biāo)識(shí)需要進(jìn)行公共字段自動(dòng)填充的方法
- 自定義切面類 AutoFillAspect,統(tǒng)一攔截加入了 AutoFill 注解的方法,通過反射為公共字段賦值
- 在 Mapper 的方法上加入 AutoFill 注解
1. 引入maven依賴
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
2. 自定義注解
package com.zsx.annotation;
import com.zsx.enumeration.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定義注解,用于標(biāo)識(shí)某個(gè)方法需要進(jìn)行功能字段自動(dòng)填充處理
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//數(shù)據(jù)庫(kù)操作類型:UPDATE INSERT
OperationType value();
}枚舉類OperationType
package com.zsx.enumeration;
/**
* 數(shù)據(jù)庫(kù)操作類型
*/
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}3. 自定義切面
package com.zsx.aspect;
import com.zsx.annotation.AutoFill;
import com.zsx.constant.AutoFillConstant;
import com.zsx.context.BaseContext;
import com.zsx.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
/**
* 自定義切面,實(shí)現(xiàn)公共字段自動(dòng)填充處理邏輯
*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入點(diǎn)
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}
/**
* 前置通知,在通知中進(jìn)行公共字段的賦值
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("開始進(jìn)行公共字段自動(dòng)填充...");
//獲取到當(dāng)前被攔截的方法上的數(shù)據(jù)庫(kù)操作類型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法簽名對(duì)象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//獲得方法上的注解對(duì)象
OperationType operationType = autoFill.value();//獲得數(shù)據(jù)庫(kù)操作類型
//獲取到當(dāng)前被攔截的方法的參數(shù)--實(shí)體對(duì)象
Object[] args = joinPoint.getArgs();
if(args == null || args.length == 0){
return;
}
Object entity = args[0];
//準(zhǔn)備賦值的數(shù)據(jù)
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根據(jù)當(dāng)前不同的操作類型,為對(duì)應(yīng)的屬性通過反射來賦值
if(operationType == OperationType.INSERT){
//為4個(gè)公共字段賦值
try {
Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//通過反射為對(duì)象屬性賦值
setCreateTime.invoke(entity,now);
setCreateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}else if(operationType == OperationType.UPDATE){
//為2個(gè)公共字段賦值
try {
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//通過反射為對(duì)象屬性賦值
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}AutoFillConstant 常量類
package com.zsx.reggie.constant;
/**
* 公共字段自動(dòng)填充相關(guān)常量
*/
public class AutoFillConstant {
/**
* 實(shí)體類中的方法名稱
*/
public static final String SET_CREATE_TIME = "setCreateTime";
public static final String SET_CREATE_USER = "setCreateUser";
public static final String SET_UPDATE_TIME = "setUpdateTime";
public static final String SET_UPDATE_USER = "setUpdateUser";
}4. 使用注解
在Mapper接口的方法上加入 AutoFill 注解
package com.sky.mapper;
@Mapper
public interface CategoryMapper {
/**
* 插入數(shù)據(jù)
* @param category
*/
@Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user)" +
" VALUES" +
" (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
@AutoFill(value = OperationType.INSERT)
void insert(Category category);
/**
* 根據(jù)id修改分類
* @param category
*/
@AutoFill(value = OperationType.UPDATE)
void update(Category category);
}完成,這樣在每次插入和更新操作的時(shí)候,就可以自動(dòng)設(shè)置更新時(shí)間和更新人id。 (不過要注意,這里的sql語句中的這幾個(gè)字段還是不能缺少)
到此這篇關(guān)于Spring開發(fā)中自定義注解的使用詳解的文章就介紹到這了,更多相關(guān)Spring自定義注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用Maven入手Spring Boot第一個(gè)程序詳解
這篇文章主要給大家介紹了關(guān)于如何利用Maven入手Spring Boot第一個(gè)程序的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-02-02
java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu)詳解
這篇文章主要介紹了java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Java中bcrypt算法實(shí)現(xiàn)密碼加密的方法步驟
我們可以在Spring Boot和SSM中實(shí)現(xiàn)密碼加密,使用bcrypt算法可以保障密碼的安全性,并且減少了手動(dòng)編寫哈希函數(shù)的工作量,本文就來詳細(xì)的介紹一下,感興趣的可以了解一下2023-08-08
Spring Cloud @RefreshScope 原理及使用
這篇文章主要介紹了Spring Cloud @RefreshScope 原理及使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Spring boot中filter類不能注入@Autowired變量問題
這篇文章主要介紹了Spring boot中filter類不能注入@Autowired變量問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09

