Sakura的苍穹外卖学习日记DAY03

如何简化公共字段

简化公共字段我们需要了解AOP相关的知识

通知类型

 前置通知

 环绕通知

后置通知

抛出异常通知

注意事项 

 用@Order注解控制执行顺序

 两种切入点表达式

 先定义一个注解 再在要添加事务的方法上添加自己写的注解 就可以在通知类型的注解后匹配到要添加事务的方法了

 

 环绕通知获取连接点的信息

    @Around("pt()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("MyAspect8 around before ...");

        //1. 获取 目标对象的类名 .
        String className = joinPoint.getTarget().getClass().getName();
        log.info("目标对象的类名:{}", className);

        //2. 获取 目标方法的方法名 .
        String methodName = joinPoint.getSignature().getName();
        log.info("目标方法的方法名: {}",methodName);

        //3. 获取 目标方法运行时传入的参数 .
        Object[] args = joinPoint.getArgs();
        log.info("目标方法运行时传入的参数: {}", Arrays.toString(args));

        //4. 放行 目标方法执行 .
        Object result = joinPoint.proceed();

        //5. 获取 目标方法运行的返回值 .
        log.info("目标方法运行的返回值: {}",result);

        log.info("MyAspect8 around after ...");
        return result;
    }

 

其他通知获取连接点信息

 

学习使用事务

事务的作用

        当程序运行出现异常(出现运行时异常) 会使程序回滚 使程序一起执行

用@Transactional注解开启事务(在Spring框架中集成好了 直接调用)

使出现所有异常都会回滚

需要在yml配置文件中添加如下配置

#spring事务管理日志
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug

使日志始终输出 

@Service
public class DeptLogServiceImpl implements DeptLogService {

    @Autowired
    private DeptLogMapper deptLogMapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    // 开启新的事务
    @Override
    public void insert(DeptLog deptLog) {
        deptLogMapper.insert(deptLog);
    }
}

 正常情况下finally 中的内容不会写入数据库

但是加了(propagation = Propagation.REQUIRES_NEW) 就会将日志写到数据库 因为是开启了一个新的事务不会受其他的事务影响

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer id) {
        try {
            // 删除部门
            deptMapper.deleteById(id);

            // 删除部门关系表数据
            empMapper.deleteByDeptId(id);
        }finally {
            DeptLog deptLog = new DeptLog();
            deptLog.setCreateTime(LocalDateTime.now());
            deptLog.setDescription("执行了解散部门的操作,此次解散的是"+id+"号部门");
            deptLogMapper.insert(deptLog);
        }
    }

接下来我们完成公共字段的简化

创建自定义注解类

/**
 * @Author: Sakura
 * @Date: 2024/8/17 17:37
 * @Version: v1.0.0
 * @Description: TODO
 * 自定义注解,用于标识需要自动填充的公共字段
 **/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

    // 数据库操作类型
    OperationType value();
}

 创建自定义注解切面类

/**
 * @Author: Sakura
 * @Date: 2024/8/17 18:43
 * @Version: v1.0.0
 * @Description: TODO
 * 自定义注解切面类 用于实现公共字段的自动填充
 **/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotaion.AutoFill)")
    public void autoFillPointCut() {}

    @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.length == 0 || args[0] == null){
            return;
        }
        Object entity = args[0];

        // 准备填充的数据
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();
        // 根据不同的操作类型,将对应的数据填充到对应的参数中
        if (operationType == OperationType.INSERT){
            // 为四个公共字段赋值
            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_CREATE_USER, Long.class);
                // 通过反射 为四个公共字段赋值
                setCreateTime.invoke(entity,now);
                setCreateUser.invoke(entity,currentId);
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                e.printStackTrace();
             }
        }else if (operationType == OperationType.UPDATE){
            // 为两个公共字段赋值
            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) {
                e.printStackTrace();
            }
        }
    }
}

 在Mapper的方法上添加@AutoFill注解实现公共字段的填充

 

使用SQL语句获取主键值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值