共计 2945 个字符,预计需要花费 8 分钟才能阅读完成。
起源:juejin.cn/post/6984555714752561183
背景
数据库设计过程中,咱们往往会给数据库表增加一些通用字段,比方创建人、创立工夫、批改人、批改工夫,在一些公司的设计过程中有时会强制要求每个表都要蕴含这些根底信息,以便记录数据操作时的一些根本日志记录。
依照平时的操作来说,通用做法是输写 sql 时,将这些信息和对象的根本属性信息一起写入数据库,当然,这也是大家司空见惯的操作,这种写法无可非议,然而对于一个高级开发人员来说,如果所有的表都进行如此操作,未免显得有点啰嗦,而且数据表多的话,这样写就有点得失相当了。
其实还有一种更简便的做法,spring 框架大家应该是比拟相熟的,简直每个公司都会用到,其中 aop 思维 (切面编程) 的经典利用场景之一就是日志记录,本文联合 aop 思维,着重介绍下 springboot 框架下如何利用切面编程思维实现将创建人、创立工夫、更新人、更新工夫等根底信息写入数据库。
外围代码
@Aspect
@Component
@Configuration
public class CommonDaoAspect {
private static final String creater = "creater";
private static final String createTime = "createTime";
private static final String updater = "updater";
private static final String updateTime = "updateTime";
@Pointcut("execution(* com.xx.xxxx.*.dao.*.update*(..))")
public void daoUpdate() {}
@Pointcut("execution(* com.xx.xxxx.*.dao.*.insert*(..))")
public void daoCreate() {}
@Around("daoUpdate()")
public Object doDaoUpdate(ProceedingJoinPoint pjp) throws Throwable {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) {return pjp.proceed();
}
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader("token");
String username = getUserName();
if (token != null && username != null) {Object[] objects = pjp.getArgs();
if (objects != null && objects.length > 0) {for (Object arg : objects) {BeanUtils.setProperty(arg, updater, username);
BeanUtils.setProperty(arg, updateTime, new Date());
}
}
}
Object object = pjp.proceed();
return object;
}
@Around("daoCreate()")
public Object doDaoCreate(ProceedingJoinPoint pjp) throws Throwable {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) {return pjp.proceed();
}
Object[] objects = pjp.getArgs();
if (objects != null && objects.length > 0) {for (Object arg : objects) {String username = getUserName();
if (username != null) {if (StringUtils.isBlank(BeanUtils.getProperty(arg, creater))) {BeanUtils.setProperty(arg, creater, username);
}
if (StringUtils.isBlank(BeanUtils.getProperty(arg, createTime))) {BeanUtils.setProperty(arg, createTime, new Date());
}
}
}
}
Object object = pjp.proceed();
return object;
}
private String getUserName() {return UserUtils.getUsername();
}
}
复制代码
代码介绍及注解阐明
1. 代码介绍
外围代码申明了一个 CommonDaoAspect 切面类,实体类中申明了 4 个外围办法和一个获取用户名信息的办法,UserUtils 是我的项目中申明的工具类,蕴含获取用户 id、姓名等一些根底信息,大家能够依据本人的理论状况去定义,不要照部就搬。
4 个外围办法中,daoUpdate 和 daoCreate 上增加了 @Pointcut 注解,该注解通过申明正则表达式来确定我的项目包中 dao 目录下哪些办法执行该切面办法。doDaoUpdate 和 doDaoCreate 办法上增加了 @Around 注解,注解中引入了上述两个办法,示意盘绕告诉, 在咱们本人 dao 目录下的对应文件指标办法实现前后做加强解决。
2. 注解阐明
- @Aspect: 申明切面类,外面能够定义切入点和告诉
- @Component:表明该类是 spring 治理的一个对象
- @Pointcut:切入点,通过正则表达式申明切入的机会,本文中是在指标办法 (即我的项目中 dao 目录下实体类中蕴含 insert 或 update 字符串的办法) 执行时退出切入信息,即执行新增或更新时退出创建人和更新人等信息。
- @Around: 盘绕告诉, 在指标办法实现前后做加强解决,本案例中示意在 doCreate 和 doUpdate 办法执行时增加参数信息
注:execution( com.xx.xxxx..dao..update(..)) 示意在 dao 目录下的任何文件中的以 update 结尾的办法
execution( com.xx.xxxx..dao..insert(..)) 示意在 dao 目录下的任何文件中的以 insert 结尾的办法
近期热文举荐:
1.1,000+ 道 Java 面试题及答案整顿(2021 最新版)
2. 别在再满屏的 if/ else 了,试试策略模式,真香!!
3. 卧槽!Java 中的 xx ≠ null 是什么新语法?
4.Spring Boot 2.5 重磅公布,光明模式太炸了!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!