Java中运用SpirngAOP的来思想实现自定义日志注解并使用

news2024/9/21 2:37:07

1.AOP的思想

面向切面编程。它是对OOP(面向对象编程)的一种补充,OOP往往是继承或者是实现都是纵向进行的,而AOP是切面编程,是横向的,它出现的目的是将我们某些与业务无关的公共代码提取出来,找到一个切点进行切入形成切面,在切面进行公共代码的插入,以此来进行增强的操作。这样我们就不用在每一个业务中都写一遍与业务无关的代码。

上面这句话可以跳过,我们还是要从问题出发,什么问题导致出现了AOP的思想及其解决方案。

问题:我们系统中一定会有日志记录吧。例如每一个Controller的增删改操作,我们都会记录一下,记录哪个用户干了什么事,如果没有AOP,可能会这样去做,封装一个统一的日志工具类,然后在每个Controller的方法中调用这个日志的方法。可能是一行代码就解决了,这里可以先透露一下,我们使用aop,也是通过一个注解的方式进行增强,那问题就来了?同样是一行代码,为什么还用aop呢而不用日志工具类呢?

解答:我举个例子,假如说我某个修改操作发生了异常,那此时你封装日志工具类就没办法处理了吧,它的关注点就只是方法内部的某一个小点,而AOP此时就可以解决这个问题,它能获取到方法的所有东西,包括返回的结果,并且通过注解的方式我就不用侵入你的业务逻辑代码,并且能在你的方法的执行前后都去做一些操作,并且使我们的代码更容易维护,因为我的方法里面就只是我的业务逻辑,我是通过注解来实现日志记录的,其次呢,如果将来你封装的工具类方法需要新添加一个参数,你自己想想吧,你是不是调用的每个地方都需要修改,而使用注解呢,我参数可传可不传,不会影响我其他的代码,可扩展性也是非常好的。
 

总结一句话:AOP就是将我们代码中的横切关注点(日志记录、事物管理)从核心业务逻辑中分离出来, 通过定义切面来统一管理这些横切关注点,在需要使用的地方,将切面进行织入即可。

AOP的优点总结:
1.横切关注点的集中管理:可以将与业务逻辑无关的功能集中到切面中,提高代码的可维护性。
2.降低代码重复和分散:将通用功能抽离出来,避免在多个对象和方法中重复实现。
3.提高代码的可读性和可维护性:将横切关注点与核心业务逻辑分离,使代码更加清晰、简洁。
4.支持横向扩展:可以在不修改原有代码的情况下,通过定义新的切面来增加功能。

2.AOP的组成

2.1连接点(Join Point)

连接点是程序执行过程中的实际事件点,可以被拦截和增强,简单说就是某个方法,要跟下面的切点明确区分开。

2.2切点(Point Cut)

切点是一个表达式或规则,用来匹配连接点,确定哪些连接点应该被AOP拦截和应用切面。

2.3通知(Advice)

就是我们需要进行的增强的操作,例如日志的记录操作,并且我们可以定义不同的通知来实现不同时机进行的增强操作,

前置通知使用 @Before:通知方法会在目标方法(即要访问的具体业务方法)调用之前执行
后置通知使用 @After:通知方法会在目标方法返回或者抛出异常后调用
返回之后通知@AfterReturning:通知方法会在目标方法返回后调用
抛异常后通知 @AfterThrowing:通知方法会在目标方法抛出异常之后调用
环绕通知@Around:通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行相应代码

2.4切面(Aspect)

切点+通知=切面。

而SpringAOP就是对AOP的一个具体实现。

3.实现自定义的日志注解

3.1 日志注解SysOperationLog

首先定义一个注解,起名@SysOperationLog,考虑一下需要哪些字段,一般就是记录某个操作的名字和类型就可。代码:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysOperationLog {
    /**
     * 业务标题 title
     * @return
     */
    String value() default "操作日志";
    /**
     *  业务类型
     * @return
     */
    BusinessTypeEnum businessType() default BusinessTypeEnum.OTHER;
}
3.2 业务类型枚举BusinessTypeEnum
@Getter
@AllArgsConstructor
public enum BusinessTypeEnum {

    // 其它
    OTHER(1,"其它"),
    // 查找
    SELECT(2,"查找"),
    // 新增
    INSERT(3,"新增"),
    // 修改
    UPDATE(4,"修改"),
    // 删除
    DELETE(5,"删除"),
    //详情
    DETAIL(6,"详情");

    private Integer code;
    private String name;

    public static String  getNameByCode(Integer code){
        for (BusinessTypeEnum value : BusinessTypeEnum.values()) {
            if(value.getCode().equals(code)){
                return value.getName();
            }
        }
        return "";
    }
}
3.3定义日志切面LogAspect

引入AOP的依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
@Component
@Aspect
public class LogAspect {

    private final String logPointcut = "execution(* com.daz.controller..*.*(..))";//切点表达式

    //切点
    @Pointcut(logPointcut)
    public void logPointcut() {
    }

    @Before(value = "logPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println("执行了前置通知");
    }

    @Around(value = "logPointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("执行了环绕通知");
        Object proceed =null;
        try{
            proceed = proceedingJoinPoint.proceed();
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            SysOperationLog sysOperationLog = signature.getMethod().getAnnotation(SysOperationLog.class);
            System.out.println(sysOperationLog.value());
            //接着你就可以在这去将注解中的日志操作保存到数据库中即可。
        }catch (Exception e){
        }
        return proceed;
    }

    @After(value = "logPointcut()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println("执行了后置通知");
    }

    @AfterReturning(value = "logPointcut()", returning = "result")
    public void afterReturn(JoinPoint joinPoint, Object result) {
        System.out.println("执行了返回通知");

    }

    @AfterThrowing(value = "logPointcut()", throwing = "exception")
    public void doAfterThrowing(JoinPoint joinPoint, Exception exception) {
        System.out.println("执行了异常通知");
    }

}
4.在对应的方法上加上我们自定义的注解@SysOperatonLog
@RequestMapping("/aaa/bbb")
    @SysOperationLog("编辑")
    public String testA() throws Exception {
        return "hello";
    }
5.测试执行结果分析

4.步骤三如何利用AOP思想进行实现的,及其相关类的讲解

大体流程总结:首先通过@Aspect和@Component来定义一个切面,在切面中定义切点(拦截规则),拦截到对应的方法以后,跳到我们定义的对应的通知方法中,在通知方法中能够获取到自定义注解的相关信息,从而取出注解,保存注解信息操作到数据库中。

首先由上述的执行结果我们知道,执行顺序,此处主要讲解环绕通知这个方法。我们主要的操作都写到这个方法中。介绍一下其中相关的类。

4.1. ProceedingJoinPoint

可以看出它继承JoinPoint,这个又称连接点的意思,那肯定就是连接点的相关信息,就像我们此时的连接点是一个方法,那肯定就是获取方法相关的信息了。

我们主要关注以上我圈出的方法。
proceed():这个就是获取我们方法的返回结果的。
getArgs():这个是获取我们方法的参数列表的。
getSignature():这个是获取我们原始的Method类的,通过该类,可以获取注解。只不过需要强转一下成为MethodSignature,再调用getMethod方法就可以获取到。

4.2 MethodSignature

首先查看关系,鼠标放到类上,快捷键ctrl+alt+u,可以看出它的父接口就是Signature,所以可以转,因为MethodSignature中提供了获取方法类Method的方法,进而获取方法上相关的信息,例如我们自定义的注解。

4.3. Method

这个就最原始的方法,它提供了我们获取方法的相关信息的各种方法,例如获取方法的注解就是其中一个。

总结:以上我们讲了SpringAOP的思想及其运用,但是它底层实际上是通过JDK动态代理或者CGLIB动态代理的方式去实现的。后续继续介绍。

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

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

相关文章

服务优雅上下线实现方案-运维

1、前言 前一篇文章介绍了nginx通过nginx_upstream_check_module模块实现后端健康检查&#xff0c;基于这篇文章介绍一下服务优雅上下线的实现方案。 对于微服务来说&#xff0c;服务的优雅上下线是必要的。对于上线来说&#xff0c;如果服务没有启动成功&#xff0c;就不应该对…

sqli-labs-master 25-30关

sqli-labs第25关 由本题意可得过滤and和or&#xff0c;我用双写进行绕过&#xff0c;例如&#xff1a;infoorrmation,aandnd 数据库名 http://127.0.0.1/sqli-labs-master/Less-25/?id-1%27%20union%20select%201,2,database()-- 表名 127.0.0.1/sqli-labs-master/Less-25…

24/8/7算法笔记 决策树分类

决策树是一种常用的机器学习算法&#xff0c;用于分类和回归任务。它通过学习简单的决策规则从数据特征中推断出目标值。以下是决策树的一些关键特点&#xff1a; 树形结构&#xff1a;决策树由一系列的问题组成&#xff0c;每个问题对应一个特征和可能的取值。这些问题按照树状…

orcad和allegro无法交互的解决方案

当Orcad和Allegro无法交互时&#xff0c;可能是由于多种原因导致的。以下是一些常见的解决方案&#xff0c;旨在帮助用户解决这一问题&#xff1a; 1. 检查并设置Enable Intertool Communication选项 首先&#xff0c;确保在Orcad Capture CIS中启用了“Enable Intertool Com…

ORM工具之SQLAlchemy

SQLAlchemy是Python编程语言下的一款开源软件。提供了SQL工具包及对象关系映射&#xff08;ORM&#xff09;工具&#xff0c;使用MIT许可证发行。 SQLAlchemy“采用简单的Python语言&#xff0c;为高效和高性能的数据库访问设计&#xff0c;实现了完整的企业级持久模型”。SQL…

javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection

这段代码中出现的异常 javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection 通常是因为客户端尝试通过非加密连接发起 HTTPS 请求&#xff0c;而服务器期望的是加密的 SSL/TLS 连接。 这个异常可能是因为以下几种情况之一&#xff1a; HTTPS 服务配置…

Element-Plus组件Tree树形控件时,传输失去父节点和回显父节点下的子节点全选问题解决

使用环境 Vue 3 in Vite Element-Plus JS语法&#xff08;非TS&#xff09; 问题描述&#xff1a; 在使用Element-Plus组件Tree树形控件时&#xff0c;会出现如下问题&#xff1a; 1、子节点未全选时&#xff0c;往后端传输的选中节点没有包含父节点。 如下图&#xff0c;…

学习大数据DAY33 Flask 库 API 开发介绍,OS 库,pandas 库和简单爬虫

目录 Python API 接口开发用法介绍 Postman 调试接口 OS 库 pandas Pandas 数据结构 - Series Pandas 处理数据方法 Pandas CSV 文件 Pandas JSON Pandas excel 文件 上机练习 11 爬虫 爬取所有数据 pandas 分析处理数据 导入到 mysql 上机练习 12---使用爬虫pan…

Ubuntu 24.04 LTS安装elasticsearch-8.14.3+Kibana

1.安装Elasticsearch 1.1 下载Elasticsearch # 1. 更新包索引 sudo apt update# 2. 升级已安装的软件包 sudo apt upgrade -y# 3. 进入 /opt 目录 cd /opt# 4. 下载Elasticsearch压缩包 sudo wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.14.…

国产化飞腾D2000独显可插拔式OPS电脑主板,应用于信创教育、信创会议、信创办公等领域

国产化飞腾D2000 主板规格书 产品概述 XM-F611是我司自主研发设计的一款独显可插拔式OPS电脑主板&#xff0c;符合Intel OPS(Open Pluggable Specification)标准规范。采用飞腾腾锐D2000八核处理器加国产独立显卡&#xff0c;搭配国产银河麒麟或统信操作系统&#xff0c;能够…

sparkhive--练习2

需求&#xff1a; 在hive中创建对应表&#xff0c;并且导入数据&#xff0c;使用spark完成对应的查询 stu_name course score 张三 语文 98 张三 数学 95 张三 英语 89 李四 语文 97 李四 数学…

【天数计算】输入某年某月某日,判断这一天是这一年的第几天

要求&#xff1a;输入某年某月某日&#xff0c;判断这一天是这一年的第几天&#xff0c;使用C语言实现 #include<stdio.h>int dayYear(int year,int month,int day){int days_in_month[] {0,31,28,31,30,31,30,31,31,30,31,30,31};int i,days0;for(i1;i<month;i){da…

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 文章目录 前言分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 一、PSO-KELM-Adaboost模型1. 核化极限学习机 (KELM)2. 粒子…

5G边缘计算网关应用

在信息技术浪潮的推动下&#xff0c;5G网络与边缘计算的结合正快速地推动着人们步入一个前所未有的智能生活新纪元。5G边缘计算网关作为两者融合的重要枢纽&#xff0c;其应用领域的拓展和优势表现越来越受到企业和行业的重视。      5G边缘计算网关的技术背景   5G网络为…

WEB应用(十三)---RCE

什么是RCE&#xff1f; Remote Command/Code Execute&#xff0c;远程命令或代码执行。通过构造特殊的字符串&#xff0c;将数据提交至Web应用程序&#xff0c;并利用该方式执行外部程序或系统命令实施攻击&#xff0c;类似于SQL注入。 Web应用程序使用了一些可以执行系统命令或…

多变量时间序列生成模型GAN介绍与实现

目录 1. 模型介绍2. 问题提出3. 模型具体实现3.1 数据预处理3.2 生成对抗网络&#xff08;GAN&#xff09;结构3.3 模式崩溃解决3.4 合成数据验证 4. 代码实现参考文献 1. 模型介绍 在大数据时代&#xff0c;生成逼真的时间序列数据对于负载平衡、负载预测和智能资源配置等方面…

openwrt 性能工具perf和cpu占用查看工具sysstat编译及使用

代码使用的lean源码&#xff0c;只需要用make menuconfig打开perf对应的编译选项即可 1.第一步选择Global build settings 2.第二步选择Kernel build options 3.第三步选择Enable kernel cgroups 4.第四步选择Enable perf_event per-cpu per-container group (cgroup) monitor…

计算机网络-CSP初赛知识点整理

历年真题 [2016-NOIP-普及-第3题] 以下不属于无线通信技术的是( ) A. 蓝牙 B. Wifi C. GPRS D. 以太网 [2015-NOIP-普及-第10题] FTP 可以用于( )。 A. 远程传输文件 B. 发送电子邮件 C. 浏览网页 D. 网上聊天 [2019-CSP-J-第1题] 中国的国家顶级域名是( ). A. .cn B. .ch C.…

国内自闭症学校指南:了解孩子的康复需求和解决方案

在国内&#xff0c;自闭症儿童的数量逐年增加&#xff0c;为他们提供专业的教育和康复支持变得至关重要。对于家长来说&#xff0c;选择一所合适的自闭症学校是帮助孩子走向康复的关键一步。在众多的选择中&#xff0c;星贝育园以其独特的优势和全面的服务脱颖而出。 当孩子被诊…

android系统中data下的xml乱码无法查看问题剖析及解决方法

背景&#xff1a; Android12高版本以后系统生成的很多data路径下的xml都变成了二进制类型&#xff0c;根本没办法看xml的内容具体如下&#xff1a; 比如想要看当前系统的widget的相关数据 ./system/users/0/appwidgets.xml 以前老版本都是可以直接看的&#xff0c;这些syste…