问题的出现
当我们进行后端开发的时候会出现很多表格都存在很多相同名称的字段如
1 2 3 4
| private LocalDateTime createTime; private LocalDateTime updateTime; private Long createUser; private Long updateUser;
|
我们在service中可能会出现多次重复的赋值操作,如:
1 2 3 4 5 6 7 8 9
| entity.setCreateTime(LocalDateTime.now()); entity.setUpdateTime(LocalDateTime.now()); entity.setCreateUser(当前登录用户ID); entity.setUpdateUser(当前登录用户ID);
entity.setUpdateTime(LocalDateTime.now()); entity.setUpdateUser(当前登录用户ID);
|
这样的代码不仅繁琐,而且容易遗漏,导致数据不一致。Spring框架为我们提供了一种优雅的解决方案——使用公共字段自动填充功能。
实现思路
- 创建公共字段注解,用于标识
1 2 3 4 5 6 7 8 9 10
| public enum OperationType { INSERT, UPDATE }
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AutoFill { OperationType value(); }
|
- 定义切面类,统一拦截加注解的方法,通过反射为公共字段赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| @Aspect @Slf4j @Component public class AutoFillAspect { @Pointcut("execution(* top.zfmx.mapper.*.*(..)) && @annotation(top.zfmx.annotation.AutoFill)") public void autoFillPointCut(){}
@Before("autoFillPointCut()") public void autoFill(JoinPoint joinPoint) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { log.info("开始公共字段的自动填充"); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
OperationType value = null; if (annotation != null) { value = annotation.value(); }
Object[] args = joinPoint.getArgs();
Object entity = args[0]; LocalDateTime now = LocalDateTime.now(); Long currentId = BaseContext.getCurrentId();
if(value == OperationType.INSERT){ 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);
setCreateTime.invoke(entity,now); setCreateUser.invoke(entity,currentId); setUpdateTime.invoke(entity,now); setUpdateUser.invoke(entity,currentId); }else if (value == OperationType.UPDATE){ 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,now); setUpdateUser.invoke(entity,currentId); } } }
|
- 在mapper加入注解
1 2 3 4 5 6
| @Mapper public interface CategoryMapper { @AutoFill(value = OperationType.UPDATE) void update(Category category); }
|
使用总结
通过以上步骤,我们成功利用Spring AOP实现了公共字段的自动填充功能。通过合理利用Spring AOP,我们可以将各种横切关注点从业务逻辑中分离出来,使应用程序更加模块化、可维护和可扩展。