Spring開發(fā)中自定義注解的使用詳解
Spring自定義注解
在Java項(xiàng)目中,可以自定義注解,方便進(jìn)行某些處理操作,提供開發(fā)效率。
比如,在進(jìn)行實(shí)體類的crud操作時(shí),一般都有create_time, createUser, updateTime, updateUser這幾個(gè)字段,而且不是核心業(yè)務(wù)代碼,這時(shí)可以引入注解簡化開發(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)一處理,來簡化開發(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ù)庫操作類型:UPDATE INSERT OperationType value(); }
枚舉類OperationType
package com.zsx.enumeration; /** * 數(shù)據(jù)庫操作類型 */ 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ù)庫操作類型 MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法簽名對(duì)象 AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//獲得方法上的注解對(duì)象 OperationType operationType = autoFill.value();//獲得數(shù)據(jù)庫操作類型 //獲取到當(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-02java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu)詳解
這篇文章主要介紹了java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Java中bcrypt算法實(shí)現(xiàn)密碼加密的方法步驟
我們可以在Spring Boot和SSM中實(shí)現(xiàn)密碼加密,使用bcrypt算法可以保障密碼的安全性,并且減少了手動(dòng)編寫哈希函數(shù)的工作量,本文就來詳細(xì)的介紹一下,感興趣的可以了解一下2023-08-08Spring Cloud @RefreshScope 原理及使用
這篇文章主要介紹了Spring Cloud @RefreshScope 原理及使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01Spring boot中filter類不能注入@Autowired變量問題
這篇文章主要介紹了Spring boot中filter類不能注入@Autowired變量問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09