今天在CSDN看文章 看到了切面实现自动填充字段,于是自己也写一个切面来实现
1 创建注解
@Target(ElementType.METHOD)//注解用在方法上
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)//注解在运行时保留
public @interface AutoFill {
//OperatorType value() 是一个枚举类型,用来标识是新增还是修改
OperatorType value();
}
下面是注解@Target()方法别的使用参数:
ElementType.TYPE
:表示注解可以用于类、接口、枚举等类型的声明上。ElementType.FIELD
:表示注解可以用于字段(成员变量)的声明上。ElementType.PARAMETER
:表示注解可以用于方法的参数上。ElementType.CONSTRUCTOR
:表示注解可以用于构造函数的声明上。ElementType.LOCAL_VARIABLE
:表示注解可以用于局部变量的声明上。ElementType.ANNOTATION_TYPE
:表示注解可以用于注解类型的声明上。ElementType.PACKAGE
:表示注解可以用于包的声明上。
下面是注解
@Retention方法别的使用参数:
RetentionPolicy.SOURCE
:表示注解仅在源代码级别保留,编译后的字节码中不包含注解信息。RetentionPolicy.CLASS
:表示注解在编译时保留,编译后的字节码中包含注解信息,但在运行时不可获取。RetentionPolicy.RUNTIME
:表示注解在编译后的字节码中保留,并且可以在运行时通过反射获取和处理注解信息。
2 实现切面处理层
我这里用的是前置通知@Before
@Aspect
@Component
@Slf4j
public class AutoFillAspectJ {
@Pointcut("@annotation(com.cloud.rapid.platform.web.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);
//获取注解的值
OperatorType value = autoFill.value();
//获取参数
Object arg = joinPoint.getArgs()[0];
if(arg==null){
log.info("自动填充参数为空");
return;
}
LocalDateTime now = LocalDateTime.now();
// //如果是插入 则获取参数 把createTime和updateTime填充进去
if(value==OperatorType.INSERT){
try {
Method setCreateTime = arg.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
Method setUpdateTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
setCreateTime.invoke(arg,now);
setUpdateTime.invoke(arg,now);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
//如果是更新 则获取参数 把updateTime填充进去
if(value==OperatorType.UPDATE){
try {
Method setUpdateTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
setUpdateTime.invoke(arg,now);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
代码分了几步运行
1 先获取方法上的签名 来判断是添加还是修改
//获取方法签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
//获取注解的值
OperatorType value = autoFill.value();
2 获取参数
//获取参数
Object arg = joinPoint.getArgs()[0];
if(arg==null){
log.info("自动填充参数为空");
return;
}
3 通过反射机制拿到类中的方法,然后用invoke方法进行赋值
Method setCreateTime = arg.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
Method setUpdateTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
setCreateTime.invoke(arg,now);
setUpdateTime.invoke(arg,now);
这样自动填充字段的切面就成功了,当然也可以用这样的方法处理别的事务