学习笔记1:JAVA实现AOP切面编程(增删改自动设置创建/修改时间等信息)

        在学习AOP面向切面编程时,在对数据库增、改操作自动设置时间信息是最多同学的入门第一课。大四有幸在实际开发中用到了,在自己写了一遍后印象更深刻了。


应用步骤如下:

        明确操作类型,定义一个枚举类,一般是增(Insert)和改(Update)操作,在企业开发中,删除用的是逻辑删除,即设置一个标志位Is_delete,0表示未删除,1表示已删除。故删除操作本质上也是一个更新操作,只是要多改一个标志位(Is_delete)。

public enum OperationType {

    /**
     * 更新操作
     */
    UPDATE,

    /**
     * 新增操作
     */
    INSERT,
    /**
     * 删除操作
     */
    DELETE

}

        自定义一个注解,用于后续标注在需要被切的方法(数据库增删改方法)上。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    //数据库操作类型:Update Insert
    OperationType value();
}

 @Target和@Retention是用来修饰注解的注解,被称之为元注解。

  • @Target的作用是指明目标,即被注解的注解(此处指AutoFill)可以用在什么地方,ElementType.METHOD表示可以用在方法上。
  • @Retention的作用是定义被注解的注解的生命周期,RetentionPolicy.RUNTIME策略表名AutoFill注解不仅被保存到class文件中,jvm加载class文件后仍然存在。

        定义切面,明确需要操作的切面。

//自定义常量
public class AutoFillConstant {

    public static final String SET_CREATE_TIME = "setCreateTime";
    public static final String SET_MODIFY_TIME = "setModifyTime";
    public static final String SET_CREATE_UNAME = "setCreateUname";
    public static final String SET_MODIFY_UNAME = "setModifyUname";
    public static final String SET_CREATE_UID = "setCreateUid";
    public static final String SET_MODIFY_UID = "setModifyUid";
    public static final String SET_IS_DELETED = "setIsDeleted";
    public static final String SET_IS_ENABLED = "setIsEnabled";
    public static final String SET_VERSION = "setVersion";

}
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    @Pointcut("execution(* com.yintai.report.service..*.*(..)) && @annotation(com.yintai.report.annonation.AutoFill)")
    public void autoFillPointCut(){}

    @Before("autoFillPointCut()")
    public void AutoFill(JoinPoint joinPoint){
        //获取到当前被拦截的方法的操作
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
        OperationType operationType = autoFill.value();//获得数据库操作类型

        //获取当前被拦截方法参数(实体对象)
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0){
            return;
        }

        Object entity = args[0];

        //为实体对象公共属性赋值
        LocalDateTime now = LocalDateTime.now();
        String uid = SecureUtil.getUserId();
        String uname = SecureUtil.getUserName();

        if (operationType == OperationType.INSERT){
            try {
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME,LocalDateTime.class);
                Method setCreateUname = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_UNAME,String.class);
                Method setCreateUid = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_UID,String.class);
                Method setIsDeleted = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_IS_DELETED,Integer.class);
                Method setIsEnabled = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_IS_ENABLED,Integer.class);
                Method setVersion = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_VERSION,Integer.class);

                setCreateUid.invoke(entity,uid);
                setCreateUname.invoke(entity,uname);
                setCreateTime.invoke(entity,now);
                setIsDeleted.invoke(entity, SqlDefaultConstant.DEFAULT_IS_DELETED);
                setIsEnabled.invoke(entity,SqlDefaultConstant.DEFAULT_IS_ENABLED);
                setVersion.invoke(entity,SqlDefaultConstant.DEFAULT_VERSION);
            }catch (Exception e){
                log.info(e.getMessage());
            }
        }else if (operationType == OperationType.UPDATE){
            try {
                Method setModifyTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_MODIFY_TIME,LocalDateTime.class);
                Method setModifyUname = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_MODIFY_UNAME,String.class);
                Method setModifyUid = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_MODIFY_UID,String.class);

                setModifyUid.invoke(entity,uid);
                setModifyUname.invoke(entity,uname);
                setModifyTime.invoke(entity,now);
            }catch (Exception e){
                log.info(e.getMessage());
            }
        }else if (operationType == OperationType.DELETE){
            try {
                Method setModifyTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_MODIFY_TIME,LocalDateTime.class);
                Method setModifyUname = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_MODIFY_UNAME,String.class);
                Method setModifyUid = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_MODIFY_UID,String.class);
                Method setIsDeleted = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_IS_DELETED,Integer.class);

                setModifyUid.invoke(entity,uid);
                setModifyUname.invoke(entity,uname);
                setModifyTime.invoke(entity,now);
                setIsDeleted.invoke(entity,1);
            }catch (Exception e){
                log.info(e.getMessage());
            }
        }
    }
}
  • @Aspect:标明当前类为一个切面类;
  • @Component:将该类注册到Spring IOC容器中;
  • @Pointcut:切入点,需要切入的位置。execution切入点表达式,第一个*表示返回值任意,com.yintai.report.service为需要切入的包名,“..*”表示当前包及其子包下所有类,“.*(..)”表示任何方法名任何参数类型;
  • @Before:在方法执行前执行。同时有@After(在方法执行后执行),@Around(环绕切入点执行),@AfterReturning(方法执行完成后执行,有异常则不执行),@AfterThrowing(切入点运行异常时执行);

        JoinPoint是切入点,可以通过getSignature()方法获取方法签名对象的详细信息,再获取方法上AutoFill注解对象,就可以该方法的操作类型。

        由于增删改的方法都是对第一个参数对象进行的操作,所有直接取args[0]进行操作,通过反射获取对象的详细方法,再根据操作类型对对象进行相应的操作。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值