公共字段自动填充
在不同的业务表中会有一些公共字段,如创建时间、修改时间、创建人、修改人等
如果每次都在service实现类中手动设置,会造成代码冗余,不便于后期维护

可以使用自定义注解和自定义切面类来优化
-
自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法
-
自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值
-
在 Mapper 的方法上加入 AutoFill 注解
实现
1.自定义注解AutoFill
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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 {
// 标识操作类型 (INSERT 或 UPDATE)
OperationType value();
}
|
其中的OperationType是一个自定义的枚举类
1
2
3
4
5
6
7
8
9
10
|
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
|
2.自定义切面AutoFillAspect
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
/**
* 自定义切面,实现公共字段的自动填充
*/
@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("公共字段自动填充...");
// 1.获取当前拦截方法的操作类型
// 获取拦截方法的签名对象
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取方法上的注解对象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
// 获取操作类型
OperationType operationType = autoFill.value();
// 2.获取当前拦截方法的参数,即实体对象
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
// 获取实体对象(Mapper方法有多个参数时,一般把实体放在第一位)
Object entity = args[0];
// 3.准备公共字段的值
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
// 4.根据操作类型,进行不同的自动填充
if (operationType == OperationType.INSERT) {
try {
// 获取实体对象的set方法
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) {
throw new RuntimeException(e);
}
} else if (operationType == 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,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
|
其中AutoFillConstant是自定义的常量类,方便统一管理
1
2
3
4
5
6
7
8
9
10
11
12
|
/**
* 公共字段自动填充相关常量
*/
public class AutoFillConstant {
/**
* 实体类中的方法名称
*/
public static final String SET_CREATE_TIME = "setCreateTime";
public static final String SET_UPDATE_TIME = "setUpdateTime";
public static final String SET_CREATE_USER = "setCreateUser";
public static final String SET_UPDATE_USER = "setUpdateUser";
}
|
3.在Mapper接口的方法上加上AutoFill注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Mapper
public interface EmployeeMapper {
/**
* 插入员工数据
* @param employee
*/
@Insert("insert into ...略")
@AutoFill(value = OperationType.INSERT)
void insert(Employee employee);
/**
* 修改员工信息
* @param employee
*/
@AutoFill(value = OperationType.UPDATE)
void update(Employee employee);
}
|
优化后记得把原本写在service实现类中的设置公共字段参数代码删除掉