萍乡网站建设哪家公司好,搜索引擎推广预算,西安网站建设开发公司怎么样,使用织梦系统建设网站教程背景
在很多场景下#xff0c;我们对需要对一些公共字段进行赋值操作#xff0c;如果我们每一个公共字段都进行代码赋值那无疑会增加很多重复无用代码#xff0c;都会导致我们的 代码臃肿#xff0c;所以我们使用AOP切面编程#xff0c;实现功能增强#xff0c;来完成公…背景
在很多场景下我们对需要对一些公共字段进行赋值操作如果我们每一个公共字段都进行代码赋值那无疑会增加很多重复无用代码都会导致我们的 代码臃肿所以我们使用AOP切面编程实现功能增强来完成公共字段自动填充功能 例子 1). 在新增数据时, 将createTime、updateTime 设置为当前时间, createUser、updateUser设置为当前登录用户ID。
2). 在更新数据时, 将updateTime 设置为当前时间, updateUser设置为当前登录用户ID。
目前,在我们的项目中处理这些字段都是在每一个业务方法中进行赋值操作,如下:
新增员工方法 /*** 新增员工** param employeeDTO*/public void save(EmployeeDTO employeeDTO) {//.......................////设置当前记录的创建时间和修改时间employee.setCreateTime(LocalDateTime.now());employee.setUpdateTime(LocalDateTime.now());//设置当前记录创建人id和修改人idemployee.setCreateUser(BaseContext.getCurrentId());//目前写个假数据后期修改employee.setUpdateUser(BaseContext.getCurrentId());///employeeMapper.insert(employee);}编辑员工方法 /*** 编辑员工信息** param employeeDTO*/public void update(EmployeeDTO employeeDTO) {//........................................///employee.setUpdateTime(LocalDateTime.now());employee.setUpdateUser(BaseContext.getCurrentId());///employeeMapper.update(employee);}实现步骤
1). 自定义注解 AutoFill用于标识需要进行公共字段自动填充的方法
2). 自定义切面类 AutoFillAspect统一拦截加入了 AutoFill 注解的方法通过反射为公共字段赋值
3). 在 Mapper 的方法上加入 AutoFill 注解 自定义注解 AutoFill
package com.sky.annotation;import com.sky.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();
}在此之前我们选择将数据库的操作类型进行封装
package com.sky.enumeration;/*** 数据库操作类型*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT
}自定义切面 AutoFillAspect
package com.sky.aspect;/*** 自定义切面实现公共字段自动填充处理逻辑*/
Aspect
Component
Slf4j
public class AutoFillAspect {/*** 切入点*/Pointcut(execution(* com.sky.mapper.*.*(..)) annotation(com.sky.annotation.AutoFill))public void autoFillPointCut(){}/*** 前置通知在通知中进行公共字段的赋值*/Before(autoFillPointCut())public void autoFill(JoinPoint joinPoint){/重要//可先进行调试是否能进入该方法 提前在mapper方法添加AutoFill注解log.info(开始进行公共字段自动填充...);}
}完善自定义切面 AutoFillAspect 的 autoFill 方法
package com.sky.aspect;import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.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;/*** 自定义切面实现公共字段自动填充处理逻辑*/
Aspect
Component
Slf4j
public class AutoFillAspect {/*** 切入点*/Pointcut(execution(* com.sky.mapper.*.*(..)) annotation(com.sky.annotation.AutoFill))public void autoFillPointCut(){}/*** 前置通知在通知中进行公共字段的赋值*/Before(autoFillPointCut())public void autoFill(JoinPoint joinPoint){log.info(开始进行公共字段自动填充...);//获取到当前被拦截的方法上的数据库操作类型MethodSignature signature (MethodSignature) joinPoint.getSignature();//方法签名对象AutoFill autoFill signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象OperationType operationType autoFill.value();//获得数据库操作类型//获取到当前被拦截的方法的参数--实体对象Object[] args joinPoint.getArgs();if(args null || args.length 0){return;}Object entity args[0];//准备赋值的数据LocalDateTime now LocalDateTime.now();Long currentId BaseContext.getCurrentId();//根据当前不同的操作类型为对应的属性通过反射来赋值if(operationType OperationType.INSERT){//为4个公共字段赋值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);//通过反射为对象属性赋值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个公共字段赋值try {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);} catch (Exception e) {e.printStackTrace();}}}
}在Mapper接口的方法上加入 AutoFill 注解
以CategoryMapper为例分别在新增和修改方法添加AutoFill()注解也需要EmployeeMapper做相同操作
package com.sky.mapper;Mapper
public interface CategoryMapper {/*** 插入数据* 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);/*** 根据id修改分类* param category*/AutoFill(value OperationType.UPDATE)void update(Category category);}