Aspect使用

news2024/11/28 4:49:17

今天在敲苍穹外卖的时候用到了 SpringBoot 中的 AOP,这里简单记录下使用过程。

背景

目前的CreateTime、CreateUser、UpdateTime、UpdateUser等字段都是在插入和更新操作时手动设置, 每次都要手动操作太麻烦,可以把这几个操作放到一块包装一下,可以用SpringBoot中的面向切面编程做到。

什么是AOP

AOP为Aspect Oriented Programming的缩写,意为面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术

常用注解

  • @Aspect: 把当前类标识为一个切面供容器读取
  • @Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
  • @Around:环绕增强,相当于MethodInterceptor。
  • @AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行。
  • @Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有。
  • @AfterThrowing:异常抛出增强,相当于ThrowsAdvice。
  • @After: final增强,不管是抛出异常或者正常退出都会执行
    这里盗用一下铿然架构的图。
    在这里插入图片描述

使用

在这里为实现公共字段填充功能大体可以分为三步,即自定义注解、自定义切面类、在Mapper层方法上加上自定义注解。

自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

    // 数据库操作,INSERT or UPDATE
    OperationType value();
}

其中OperationType为枚举类,代码如下:

public enum OperationType {
    /**
     * 更新操作
     */
    UPDATE,

    /**
     * 插入操作
     */
    INSERT

}

自定义切面类

写完自定义注解后,需要再写切面类

@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
     * @Description ToDo 定义切点,指定需要拦截的方法
     */
    // 这里execution中第一个 * 是返回类型,指返回值是所有的类型,这里要给mapper包下且带AutoFill自定义注解的方法加入切入点
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill) ")
    public void autoFillPointCut(){}

    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("AutoFillAspect自动填充数据");
        // 1.获取操作类型
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
        OperationType operationType = autoFill.value();

        // 2.获取被拦截的方法的参数
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0){
            return;
        }
        Object entity = args[0];

        // 3.准备赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

        // 4.根据不同的操作类型进行不同的赋值
        switch (operationType){
            case 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_UPDATE_USER, Long.class);

                    setCreateTime.invoke(entity, now);
                    setCreateUser.invoke(entity, currentId);
                    setUpdateTime.invoke(entity, now);
                    setUpdateUser.invoke(entity, currentId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case 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();
                }
                break;
            default:
                return;
        }
    }
}

在Mapper层添加方法

以为只有在执行 INSERTUPDATE 操作时才需要填充字段,所以这里只需要给 insert 和 update 方法加入 @AutoFill 注解就可以。
@Mapper
public interface EmployeeMapper {

    /**
     * 根据用户名查询员工
     * @param username
     * @return
     */
    @Select("select * from employee where username = #{username}")
    Employee getByUsername(String username);

    /**
     * 根据用户名查询员工
     * @param employee
     * @return
     */
    @Insert("insert into employee(name,username,password,phone,sex,id_number,create_time,update_time,create_user,update_user,status)" +
            "values" +
            "(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")
    @AutoFill(value = OperationType.INSERT)
    void insert(Employee employee);

    /**
     * 员工信息分页查询
     * @param employeePageQueryDTO
     * @return PageResult
     */
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

    /**
     * 员工信息修改
     * @param employee
     * @return PageResult
     */
    @AutoFill(value = OperationType.UPDATE)
    void update(Employee employee);

    /**
     * 根据id查询员工信息
     * @param id
     * @return PageResult
     */
    @Select("select * from employee where id = #{id}")
    Employee getById(Integer id);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1562652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端开发的主要语言有哪些?

1、HTML (HyperText Markup Language) 作用&#xff1a;HTML是构建网页内容的基础&#xff0c;是一种标记语言&#xff0c;用来定义网页的结构&#xff0c;如标题、段落、列表、表格、图像、链接等元素。优点&#xff1a;易于学习&#xff0c;广泛兼容&#xff0c;标准化程度高…

【MATLAB源码-第27期】基于matlab的QPSK定时同步仿真,采用gardner算法,Costa锁相环。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 QPSK&#xff0c;有时也称作四位元PSK、四相位PSK、4-PSK&#xff0c;在坐标图上看是圆上四个对称的点。通过四个相位&#xff0c;QPSK可以编码2位元符号。图中采用格雷码来达到最小位元错误率&#xff08;BER&#xff09; —…

双目测距项目 | 在Jetson-Nano平台上部署SGBM深度测距+YOLOv5目标检测算法

项目应用场景 面向在 Jetson Nano 平台上部署 SGBM 深度测距和基于 YOLOv5 的目标检测算法&#xff0c;实现双目测距的功能。 项目流程与效果&#xff1a; 项目细节 > 具体参见项目 README.md项目获取 https://download.csdn.net/download/weixin_42405819/89051043

【经验分享】Ubuntu下如何解决问题arm-linux-gcc:未找到命令

【经验分享】Ubuntu下如何解决问题arm-linux-gcc&#xff1a;未找到命令 前言问题分析解决方法 前言 在编译过程中发现一个问题&#xff0c;明明之前安装了gcc-4.6版本&#xff0c;版本信息都是正常显示的&#xff0c;刚安装上去的时候也是可以用的。但不知道什么原因突然不能…

Linux多进程通信(3)——详细说说共享内存原理及使用例程

1.共享内存原理及优缺点 共享内存的原理便是将相同的一片物理内存映射到进程A和进程B不同的逻辑地址空间&#xff0c;两个进程同时访问这块物理内存&#xff08;共享内存&#xff09;。 1&#xff09;优点 共享内存是进程间通信访问速度最快。 例如消息队列&#xff0c;FIFO&…

【MATLAB源码-第21期】基于matlab的BCH码编码译码仿真,调制使用QPSK,对比编码与未编码的误码率曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 QPSK调制解调&#xff1a;QPSK&#xff08;Quadrature Phase Shift Keying&#xff09;调制解调**是一种数字调制技术&#xff0c;通常用于数字通信系统。 调制&#xff1a; 1. 首先&#xff0c;将数字信号分成两路&#xff…

Django创建多app应用

目录 1. 引言 2. 多app创建的两种方式 2.1 多个app结构 2.2 单个apps多个app 3. 最后 1. 引言 在平常业务开发中&#xff0c;我们遇到的功能可能会有很多&#xff0c;单个app的应用可能无法满足我们 这个时候&#xff0c;我们就需要多app应用&#xff0c;例如&#xff1a…

22-应用构建三剑客:Pflag、Viper、Cobra核心功能介绍

如何构建应用框架 想知道如何构建应用框架&#xff0c;首先你要明白&#xff0c;一个应用框架包含哪些部分。在我看来&#xff0c;一个应用框架需要包含以下3个部分&#xff1a; 命令行参数解析&#xff1a;主要用来解析命令行参数&#xff0c;这些命令行参数可以影响命令的运…

【Servlet基础】Servlet项目创建

目录 一、认识Servlet 1.1、认识Tomcat 1.2、Servlet是什么 1.3、Servlet主要工作 二、实现第一个Servlet项目 2.1、创建Maven项目 2.2、引入依赖 2.3、创建目录结构 2.4、编写servlet代码 2.5、打包 2.6、部署 2.7、验证程序 三、利用smart Tomcat插件一键完…

【Frida】【Android】08_爬虫之网络通信库okhttp3

&#x1f6eb; 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…

【数据结构】AVL 树

文章目录 1. AVL 树的概念2. AVL 树节点的定义3. AVL 树的插入4. AVL 树的旋转5. AVL 树的验证6. AVL 树的删除7. AVL 树的性能 前面对 map / multimap / set / multiset 进行了简单的介绍【C】map & set&#xff0c;在其文档介绍中发现&#xff0c;这几个容器有个共同点是…

152 Linux C++ 通讯架构实战7 ,makefile编写改成for cpp,读配置文件,内存泄漏查找,设置标题实战

读写配置文件代码实战。nginx.conf 一个项目要启动&#xff0c;需要配置很多信息&#xff0c;第一项就是学习如何配置一个项目 nginx.conf的内容 #是注释行&#xff0c; #每个有效配置项用 等号 处理&#xff0c;等号前不超过40个字符&#xff0c;等号后不超过400个字符&#…

时序分解 | Matlab实现GSWOA-VMD改进鲸鱼优化算法优化变分模态分解时间序列信号分解

时序分解 | Matlab实现GWO-CEEMDAN基于灰狼算法优化CEEMDAN时间序列信号分解 目录 时序分解 | Matlab实现GWO-CEEMDAN基于灰狼算法优化CEEMDAN时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现GSWOA-VMD改进鲸鱼优化算法优化变分模态分解时间序…

《编程菜鸟学 Python 数据分析》让工作自动化起来!

随着我国企业数字化和信息化的深入&#xff0c;企业对办公自动化的效率和灵活性要求越来越高。Python作为一种开源的软件应用开发方式&#xff0c;通过提供强大丰富的库文件包&#xff0c;极大地简化了应用开发过程&#xff0c;降低了技术门槛。Python开发有哪些优势、挑战以及…

NB-IOT——浅谈NB-IOT及模块测试

浅谈NB-IOT及模块基本使用测试 介绍什么是NB-IOT&#xff1f;NB-IOT的特点 使用准备基本使用 总结 介绍 什么是NB-IOT&#xff1f; NB-IoT&#xff0c;即窄带物联网&#xff08;Narrowband Internet of Things&#xff09;&#xff0c;是一种低功耗广域物联网&#xff08;LPW…

Python学习从0到1 day20 第二阶段 面向对象 ② 封装

缘分 朝生暮死犹如露水 —— 24.4.1 学习目标&#xff1a; 1.理解封装的概念 2.掌握私有成员的使用 一、面向对象三大特性&#xff1a; 面向对象编程&#xff0c;是许多编程语言都支持的一种编程思想 简单理解是&#xff1a;基于模板&#xff08;类&#xff09;去创建实体&…

Lua 和 Love 2d 教程 二十一点朴克牌 (上篇lua源码)

GitCode - 开发者的代码家园 Lua版完整原码 规则 庄家和玩家各发两张牌。庄家的第一张牌对玩家是隐藏的。 玩家可以拿牌&#xff08;即拿另一张牌&#xff09;或 停牌&#xff08;即停止拿牌&#xff09;。 如果玩家手牌的总价值超过 21&#xff0c;那么他们就爆掉了。 面牌…

Tulsimer® CH-99硼选择吸附树脂在超纯水除硼领域的卓越应用与优势

超纯水&#xff08;UPW&#xff09;是一种高度纯净的水体形态&#xff0c;通过一系列精密的净化步骤&#xff0c;几乎去除了所有非氢氧成分&#xff0c;包括但不限于微生物、有机污染物及矿物质微量元素。其制备流程涵盖了预处理、反渗透、离子交换、蒸馏、紫外线或超滤等多种高…

成都三环旁的数字影像文创产业园,建设热度高,创新活力足

在成都市金牛区的“九里九园”簇群建设中心区域&#xff0c;一座充满活力的国际数字影像产业园正在崛起。这个成都数字产业园不仅建设热度高涨&#xff0c;更以其创新活力吸引了无数目光。作为数字产业的重要一环&#xff0c;它正在为成都乃至全球的数字文创产业描绘出一幅充满…

plasmo内容UI组件层级过高导致页面展示错乱

我使用plasmo写了一个行内样式的UI组件&#xff0c;但是放到页面上之后&#xff0c;会和下拉组件出现层级错乱&#xff0c;看了一下样式&#xff0c;吓我一跳&#xff1a;层级竟然设置的如此之高 所以就需要将层级设置低一点&#xff1a; #plasmo-shadow-container {z-index: …