來源: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 重磅發佈,黑暗模式太炸了!
覺得不錯,別忘了隨手點贊+轉發哦!