嘎里三分熟
  • 首页
  • JMusic
  • TSBay
  • 常用工具
  • About Me
  • 留言板
一行代码一世浮生
  1. 首页
  2. Java web
  3. Spring基础
  4. 正文

利用AOP+反射实现保存数据时自动修改属性(如修改时间)

2018年01月08日 2969点热度 7人点赞 0条评论

一、背景

    在对一个老项目进行二期的开发时,发现很多实体类并没有这是创建时间、修改时间等属性,所以打算着实解决之。由于 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(){
    }
}

三、弊端

    首先是执行效率较原来低了一点点,

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: AOP DAO repository 反射
最后更新:2018年01月08日

GoldenJet

爱折腾技术的90后漫威小死忠程序员一枚

点赞
< 上一篇
下一篇 >

文章评论

取消回复

通过电子邮件订阅博客

分类目录
  • BootStrap (2)
  • Bug集中营 (6)
  • Java web (3)
  • JavaScript (7)
  • Java基础 (17)
  • Java工具 (5)
  • Linux (3)
  • Python (3)
  • SpringBoot (14)
  • Spring基础 (8)
  • thymeleaf (1)
  • 娱乐 (3)
  • 小谈 (2)
  • 常用工具 (7)
  • 技术分析集 (5)
  • 技能 (10)
  • 源码 (4)
  • 科普类 (1)
  • 算法 (9)
  • 踩坑记 (5)
文章归档
  • 2020年11月 (1)
  • 2020年7月 (1)
  • 2020年4月 (2)
  • 2020年3月 (1)
  • 2020年1月 (1)
  • 2019年11月 (1)
  • 2019年10月 (1)
  • 2019年9月 (1)
  • 2019年8月 (1)
  • 2019年7月 (2)
  • 2019年5月 (2)
  • 2019年4月 (2)
  • 2019年3月 (3)
  • 2019年2月 (2)
  • 2019年1月 (2)
  • 2018年12月 (2)
  • 2018年11月 (3)
  • 2018年10月 (3)
  • 2018年9月 (2)
  • 2018年8月 (3)
  • 2018年7月 (2)
  • 2018年5月 (1)
  • 2018年4月 (3)
  • 2018年3月 (2)
  • 2018年2月 (3)
  • 2018年1月 (5)
  • 2017年12月 (2)
  • 2017年11月 (3)
  • 2017年10月 (1)
  • 2017年9月 (1)
  • 2017年8月 (1)
  • 2017年7月 (7)
  • 2017年6月 (5)
  • 2017年5月 (1)
  • 2017年4月 (2)
  • 2017年3月 (4)
  • 2017年2月 (2)
小伙伴友链
  • 前端驿站

COPYRIGHT © 2017-2020 嘎里三分熟. ALL RIGHTS RESERVED.

浙ICP备17005575号-1

浙公网安备 33010802009043号