Springboot中的AOP面向切面编程

目录

AOP

介绍

实现步骤

什么情况下使用

自定义的注解

自定义切面类AutoFillAspect

在Mapper的方法中加入AutoFill注解

AOP

介绍

AOP是一种面向切面编程的范式,AOP通过动态代理的方式实现对方法的拦截和处理。在运行时,AOP框架会自动生成代理对象,将切面逻辑织入到目标对象的方法中,实现对方法的增强和修改。通过将横切关注点从主要业务逻辑中分离出来,提高了代码的可读性、可维护性和可重用性。它通过切面和连接点的概念来实现,可以用于解决许多常见的横切关注点问题

实现步骤

  • 自定义注解AutoFIll,用于表示需要进行公共字段自动填充的方法

  • 自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法

  • 在Mapper的方法中加入AutoFill注解

什么情况下使用

当我们设计到多个共同操作时可以使用,比如在插入和更新数据时,我们需要为实体类添加当地时间以及操作人的userid,我们可以在service中涉及到该操作的方法添加我们自定义的注解,然后在自定义的切面类中获取方法的一些数据,并根据请求方法来进行不同的反射操作

自定义的注解

自定义注解annotation

import com.sky.enumeration.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 自定义注解,用于标识某个方法需要进行字段自动填充
 */
@Retention(RetentionPolicy.RUNTIME) //保留到运行阶段
@Target(ElementType.METHOD)  //只能加在方法上
public @interface AutoFill {
//    数据库操作类型
    OperationType value();
}
​
//OperationType为枚举类型,我们需要对update和insert进行拦截
public enum OperationType {
    UPDATE,
    INSERT
}

自定义切面类AutoFillAspect

@Aspect
@Component
@Slf4j
public class AutoFillAspect {
​
    /**
     * 切入点
     * com.sky.mapper包下包含AutoFill注解的所有类和方法
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut() {
    }
​
    /**
     * 前置通知,在通知中进行公共字段的赋值
     */
    //@Before 当autoFillPointCut扫描到带有AutoFill方法时,执行这里
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) {
        log.info("开始进行公共字段自动填充");
 // 获取到当前拦截的方法上的数据库操作类型获取方法签名对象
  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();
   Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型,为对应的属性通过反射来赋值
   if (operationType == OperationType.INSERT) {
//  为4个公共字段赋值
       try {
           Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
           Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
           Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
           Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
// 通过反射为对象赋值
          setCreateTime.invoke(entity, now);
          setCreateUser.invoke(entity, currentId);
          setUpdateTime.invoke(entity, now);
          setUpdateUser.invoke(entity, currentId);
           } catch (Exception e) {
                throw new RuntimeException(e);
            }
​
        } else if (operationType == operationType.UPDATE) {
// 为2个公共字段赋值
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
// 通过反射为对象赋值
                setUpdateTime.invoke(entity, now);
                setUpdateUser.invoke(entity, currentId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

在Mapper的方法中加入AutoFill注解

//添加AutoFill可以被AutoFillAspect拦截

//添加AutoFill可以被AutoFillAspect拦截
@AutoFill(OperationType.INSERT)
void insert(Employee employee);
@AutoFill(OperationType.UPDATE)
void update(Employee employee);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值