使用AOP思想实现开闭原则下的流水日志输出

主要实现思想:

通过实现Convert接口来抽取公共组件,获取想要的标准模型。

现在有两个订单场景,一个保存订单,一个为更新订单。构造如下的服务类:

import org.springframework.stereotype.Service;

@Service
public class OrderService {
    @RecordOperate(desc = "保存订单", convertLog = SaveOrderConvert.class)
    public Boolean saveOrder(SaveOrder saveOrder){
        System.out.println("save order, orderId:"+ saveOrder.getId());
        return true;
    }

    @RecordOperate(desc = "更新订单", convertLog = UpdateOrderConvert.class)
    public Boolean updateOrder(UpdateOrder updateOrder){
        System.out.println("update order, orderId:"+updateOrder.getOrderId());
        return true;
    }
}

对应的bean中订单属性名称会有差异,如何优雅的解决,后面会用一个转换接口,来获取对应的日志类。

定义的注释属性如下:

(这里有个注意点:

@Retention(RetentionPolicy.RUNTIME)注解用于表示注解的保留策略,在运行时保留注解,意味着注解不仅会被编译到字节码文件中。

@Target({ElementType.METHOD, ElementType.TYPE}) 表示该注解可以应用于方法和类(包括接口、枚举)上。

@Target({ElementType.METHOD,ElementType.TYPE})
@Component
@Retention(RetentionPolicy.RUNTIME)
public @interface RecordOperate {
    String desc() default "";
    Class<? extends Convert> convertLog();
}

我们要将SaveOrder和UpdateOrder转换成对应的日志模型,用于日志输出:

public interface Convert<T> {
    OperateLogDO convert(T t);
}
@Data
public class OperateLogDO {
    private Long orderId;
    private String result;
    private String desc;
}

最终针对不同的订单类实现对应的转换类:

public class SaveOrderConvert implements Convert<SaveOrder>{

    @Override
    public OperateLogDO convert(SaveOrder saveOrder) {
        OperateLogDO operateLogDO = new OperateLogDO();
        operateLogDO.setOrderId(saveOrder.getId());
        return operateLogDO;
    }
}

最终!实现AOP的横向切面逻辑,要注意这边日志打印的过程应为异步,通过注解获取日志转换实例:

@Service
@Aspect
public class OperateLogAspect {
    /**
     * 定义切入点
     */
    @Pointcut("@annotation(com.openapi.weekcode.aop.RecordOperate)")
    public void pointcut(){}

    private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            1,1,1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100)
    );

    /**
     * 定义横向逻辑
     */
    @Around("pointcut()")
    private Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = proceedingJoinPoint.proceed();
        threadPoolExecutor.execute(() ->{
            try {
                MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
                RecordOperate annotation = methodSignature.getMethod().getAnnotation(RecordOperate.class);
                Class<? extends Convert> convert = annotation.convertLog();
                Convert logConvert =  convert.newInstance();
                OperateLogDO operateLogDO = logConvert.convert(proceedingJoinPoint.getArgs()[0]);
                operateLogDO.setDesc(annotation.desc());
                operateLogDO.setResult(result.toString());
                System.out.println("insert operateLog:"+ operateLogDO.toString());
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });
        return result;
    }

}

结果如下

相关推荐

  1. 使用Spring AOP实现对外接口日志自动打印

    2024-07-10 12:04:01       40 阅读
  2. 软件设计原则-原则

    2024-07-10 12:04:01       42 阅读
  3. 软件设计原则原则

    2024-07-10 12:04:01       18 阅读
  4. 05.原则(Open Closed Principle)

    2024-07-10 12:04:01       43 阅读
  5. 设计模式之原则

    2024-07-10 12:04:01       45 阅读
  6. 原则(Open Closed Principle)

    2024-07-10 12:04:01       23 阅读
  7. 面向对象设计之原则

    2024-07-10 12:04:01       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 12:04:01       4 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 12:04:01       5 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 12:04:01       4 阅读
  4. Python语言-面向对象

    2024-07-10 12:04:01       5 阅读

热门阅读

  1. 前端判断场景和方式

    2024-07-10 12:04:01       9 阅读
  2. AWS EKS上GPU工作负载自动扩缩容的异常排查指南

    2024-07-10 12:04:01       9 阅读
  3. 深入WebKit内核:揭秘HTML与XML的识别之谜

    2024-07-10 12:04:01       8 阅读
  4. shell脚本实现mysql 数据库备份

    2024-07-10 12:04:01       9 阅读
  5. 数据结构第11节: B树

    2024-07-10 12:04:01       12 阅读
  6. Spring Boot与RSocket的集成

    2024-07-10 12:04:01       11 阅读
  7. 责任链模式

    2024-07-10 12:04:01       9 阅读