Aop-利用自定义注解和Aop 反射 注入 createTime 和 updateTime

一、前言

createTime和updateTime 这种字段,在写业务代码时很容易漏掉。而且在业务代码里面 每次都要关注这个字段手动 set一下很繁琐。

二、代码

利用Aop切面 和 反射 和自定义注解可以单独在一个地方管理这种 与业务无关的字段。

1、OperateAnnotion自定义注解

package com.mangoubiubiu.annotation;


import java.lang.annotation.*;

/**
 * @author mangoubiubiu
 */
//作用在类,方法,字段上
@Target(value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)//注解可以在运行期的加载阶段被加载到Class对象中。那么在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,从而执行不同的程序代码段
@Documented//是被用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。
public @interface OperateAnnotion {
    Class[] exclude() default {}; //需要注入实体类的class
    String [] operateFileds() default {"createTime","updateTime"};//字段名
    String idKey() default "";//实体类的id 通过idKey 来取value
}

2、OperateAspect切面类

package com.mangoubiubiu.aspect;


import cn.hutool.core.util.ReflectUtil;
import com.mangoubiubiu.annotation.OperateAnnotion;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * @author mangoubiubiu
 * 切面类 注入createTime updateTime
 */
@Aspect
@Component
@Slf4j
public class OperateAspect {

    /**
     * 切入点
     */
    @Pointcut("@annotation(com.mangoubiubiu.annotation.OperateAnnotion)")
    public void pointCut(){}


    /**
     * 环绕通知
     * @param joinPoint
     * @return
     */
    @Around("@annotation(operateAnnotion)")
    public Object around(ProceedingJoinPoint joinPoint, OperateAnnotion operateAnnotion){

        //获取class
        List<Class> classes = Arrays.asList(operateAnnotion.exclude());
        //获取要修改的字段
        List<String> fields = Arrays.asList(operateAnnotion.operateFileds());
        //获取要判断的id名
        String idKey= operateAnnotion.idKey();
        Object[] args=   joinPoint.getArgs();
        try {
            for(int i = 0; i<args.length; i++){
                //通过反射获取当前实体类的id,用来判断是修改操作还是新增操作
                for(int j=0;j<classes.size();j++){
                 if(args[i].getClass() == classes.get(j)){
                     Object o =args[i];
                     //ReflectUtil为hutool反射的工具类
                     Field field = ReflectUtil.getField(args[i].getClass(), idKey);
                     field.setAccessible(true);//关闭安全检查
                     String ids = (String)field.get(o);//通过反射拿到当前实体类的id
                     field.setAccessible(false);
                     //id为空则为新增  createTime UpdateTime都要加
                     if(StringUtils.isBlank(ids)){
                         fields.forEach((str->{
                             ReflectUtil.setFieldValue(o,str, LocalDateTime.now());
                         }));
                     }else{
                         ReflectUtil.setFieldValue(o,fields.get(1), LocalDateTime.now());//默认第二个为updateTime
                     }
                 }
                }
            }
            //执行目标方法
            Object result = joinPoint.proceed();
            return result;
        }catch (Throwable e){
            log.error(e.getMessage());
        }
        return null;
    }
}

3、业务Service    operateFileds没有写 默认有个默认值

    /**
     * 保存或者修改单条学生记录
     * @param student
     */
    @OperateAnnotion(exclude = {Student.class},idKey = "stuId")
    @Override
    public void saveOrUpdate(Student student) {
        //id为空为新增
        if(StringUtils.isBlank(student.getStuId())){
            student.setStuId(UUID.randomUUID().toString().replaceAll("-",""));
            studentMapper.insertStudent(student);
        }else {
            studentMapper.updateStudent(student);
        }
    }

三、测试

新增

 

 成功注入

修改

 

 

 注入成功

SUCCESS

 

posted @ 2021-12-27 22:07  KwFruit  阅读(300)  评论(0编辑  收藏  举报