一、背景
在对一个老项目进行二期的开发时,发现很多实体类并没有这是创建时间、修改时间等属性,所以打算着实解决之。由于 DAO 层是使用的 JPA 来实现的,并且不想对 DAO 层进行大改刀,遂决定利用 AOP 进行封装以下 DAO 层的的所有 save() 方法。
二、实现
实现其实很简单,由于偷懒,不想去自定义注解,所以就写了个 AOP 来监测 DAO 层的所有方法,对其参数进行修改,利用的反射的原理,获得对应的 set 方法,然后用该方法对修改时间和修改人进行重新赋值,简版的实现逻辑很简单,源码如下:
import lombok.extern.log4j.Log4j;
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.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
/**
* @Author: Jet
* @Description: 自定义 AOP 增强 DAO 层 save 方法
* (自动赋值修改时间和修改人)
* @Date: 2017/12/26 9:31
*/
@Component
@Aspect
@Log4j
public class EnhanceSave {
// 切点(设置在 DAO 层的)
@Pointcut(value = "execution(* com.wailian.repository.*.save(..))")
public void EnhanceSavePointCut(){}
// 前置增强
@Before(value = "EnhanceSavePointCut()")
public void before(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
if (args.length == 1) {
Object arg = args[0];
Class<?> aClazz = arg.getClass();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
StaffProfile loginStaff = principal == null ? new StaffProfile("001") : (StaffProfile) principal;
Timestamp updateTime = new Timestamp(System.currentTimeMillis());
//反射获取实体对象中的方法
try {
Method setLastUpdateStaff = aClazz.getDeclaredMethod("setLastUpdateStaff", StaffProfile.class);
if (null != setLastUpdateStaff) setLastUpdateStaff.invoke(arg, loginStaff);
} catch (NoSuchMethodException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】没有 setLastUpdateStaff 方法");
} catch (IllegalArgumentException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】使用 setLastUpdateStaff 方法时参数错误");
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】,使用 setLastUpdateStaff 方法错误");
}
try {
Method setLastUpdateDate = aClazz.getDeclaredMethod("setLastUpdateDate", Timestamp.class);
if (null != setLastUpdateDate) setLastUpdateDate.invoke(arg, updateTime);
} catch (NoSuchMethodException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】没有 setLastUpdateDate 方法");
} catch (IllegalArgumentException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】使用 setLastUpdateDate 方法时参数错误");
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】,使用 setLastUpdateDate 方法错误");
}
try {
Method getCreateStaff = aClazz.getDeclaredMethod("getCreateStaff");
Object createStaff;
if (null != getCreateStaff) {
createStaff = getCreateStaff.invoke(arg);
if (null == createStaff) aClazz.getDeclaredMethod("setCreateStaff", StaffProfile.class).invoke(arg, loginStaff);
}
} catch (NoSuchMethodException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】没有 getCreateStaff/setCreateStaff 方法");
} catch (IllegalArgumentException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】使用 setCreateStaff 方法时参数错误");
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】,使用 getCreateStaff/setCreateStaff 方法错误");
}
try {
Method getCreateDate = aClazz.getDeclaredMethod("getCreateDate");
Object createDate;
if (null != getCreateDate) {
createDate = getCreateDate.invoke(arg);
if (null == createDate) aClazz.getDeclaredMethod("setCreateDate", Timestamp.class).invoke(arg, updateTime);
}
} catch (NoSuchMethodException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】没有 getCreateDate/setCreateDate 方法");
} catch (IllegalArgumentException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】使用 setCreateDate 方法时参数错误");
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("repository 增强 save 方法: 类【" + arg.getClass() + "】,使用 getCreateDate/setCreateDate 方法错误");
}
}
}
public void after(){
}
}三、弊端
首先是执行效率较原来低了一点点,


文章评论