在開發中經常面臨對于一些公共字段的賦值。
如在下表中:
如何讓程序自動為我們需要賦值的公共字段進行賦值,避免在業務代碼中重復寫這些公共字段的賦值代碼
如下圖所示:
實現思路:
1.自定義注解AutoFill,用于標識需要進行公共字段自動填充的方法
2.自定義切面類AutoFillAspect,統一攔截加入了AutoFill 注解的方法,通過反射為公共字段
3.在Mapper的方法上加入 AutoFill 注解
實現步驟:
1.自定義注解
package com.yang.annotation;import com.yang.enumeration.OperationType;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 AutoFill {//指定數據庫操作類型: UPDATE INSERTOperationType value();}
2.自定義切面類AutoFillAspect
package com.yang.aspect;import com.yang.annotation.AutoFill;
import com.yang.constant.AutoFillConstant;
import com.yang.context.BaseContext;
import com.yang.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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;/*** 自定義切面,實現公共字段填充處理邏輯*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {//指定切入點@Pointcut("execution(* com.yang.mapper.*.*(..)) && @annotation(com.yang.annotation.AutoFill)")public void autoFillPointCut(){}/*** 設置前置通知為公共字段賦值*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint){log.info("開始公共字段的填充...");//獲取當前被攔截的方法的數據庫類型//方法簽名對象//因為需要訪問特定于方法的信息,比如方法名、返回類型、參數類型等,所以需要向下轉型為 MethodSignatureMethodSignature signature = (MethodSignature)joinPoint.getSignature();AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);OperationType type = autoFill.value();//獲取被攔截方法的參數--實體對象Object[] args = joinPoint.getArgs();if (args==null||args.length ==0){return;}Object entity = args[0];//準備賦值的數據LocalDateTime time = LocalDateTime.now();Long id = BaseContext.getCurrentId();//根據當前不同的操作類型,為對應的屬性賦值(通過反射)if (type.equals(OperationType.INSERT)){//為四個公共字段賦值try {//使用反射動態獲取set方法并且指定方法所接收的參數類型Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通過反射進行賦值setCreateTime.invoke(entity,time);setUpdateTime.invoke(entity,time);setCreateUser.invoke(entity,id);setUpdateUser.invoke(entity,id);} catch (Exception e) {throw new RuntimeException(e);}}else if (type.equals(OperationType.UPDATE)){//為兩個公共字段賦值try {//使用反射動態獲取set方法并且指定方法所接收的參數類型Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通過反射進行賦值setUpdateTime.invoke(entity,time);setUpdateUser.invoke(entity,id);} catch (Exception e) {throw new RuntimeException(e);}}}}
3.在Mapper的方法上加入 AutoFill 注解
比如:
4.測試
修改前的Category表
修改方法:
新增方法:
表結果:
參考:Day03-03-公共字段自動填充_代碼開發_2_嗶哩嗶哩_bilibili