Aop面向切面实现开发日志收集打印一文轻松搞定,内附详细图文示例+源码自取

目录

介绍

动态代理

jdk动态代理

cglib动态代理

注解实现Aop 

添加必须依赖

添加Atm类 (主业务逻辑代码块)

 定义打印log方法(提取公共代码逻辑块)

启用代理 

切点表达式

Aop通知类型 

前置通知(@Before)

后置通知(@After)

正常结束通知(@AfterReturning)

异常结束通知(@AfterThrowing)

环绕通知

 切面的优先级

 Aop使用注意点

方法权限不能是private

其他方法在内部被调用时不会被增强

注解实现Aop

基于注解实现服务层打印入参和返回参数日志

未使用Aop效果

使用注解实现Aop入参返回值等日志打印

示例源码


介绍

AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,可以在不改变原有代码的情况下,通过在程序的各个关键点上增加切面(Aspect)的方式,实现对代码的增强和横切关注点的分离,从而提高代码的可重用性、可维护性和可扩展性。

AOP的核心思想是将程序中的不同关注点进行解耦,避免不同的关注点相互嵌入,导致代码冗长、难以维护的问题。通过将不同的关注点抽象成切面,实现了程序的层次性,使得不同层次中的各种关注点可以独立地进行开发、管理和维护。

在实现AOP时,需要定义切点(Pointcut)和切面(Aspect)两个概念。切点用于定义程序中需要增强的关键点,例如方法的调用、异常抛出、对象的初始化等等。切面则是对切点进行增强的具体实现,例如日志记录、性能监测、事务管理等等。AOP框架通过在程序中动态生成代理对象的方式,将切面织入到切点上,从而实现对程序的增强。

在Java中,常用的AOP框架包括Spring AOP和AspectJ。Spring AOP是基于代理的AOP框架,可以通过配置文件或注解的方式实现切面的定义;而AspectJ是基于注解的AOP框架,可以直接在Java代码中使用注解的方式定义切点和切面。

动态代理

动态代理是一种用于实现面向切面编程的技术。它允许您编写一些代码来控制某个类或接口的行为。它可以在不更改原始代码的情况下改变或增强类的行为。当类的对象被创建时,动态代理会在内存中创建一个新的类和一个代理类,以控制原始类的行为。

下面看一个代码示例:

 测试

可以看到这里两个方法除了各自方法的核心业务逻辑外,方法执行前和执行后是重复的非核心业务代码,这里方法只有两个,如果方法成百上千时就需要改很多的地方,从而可以使用动态代理进行优化处理

jdk动态代理

JDK动态代理是通过Java自带的反射机制实现的,主要涉及两个类:java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler

Proxy类是JDK提供的动态代理类,它提供了用于创建动态代理对象的静态方法newProxyInstance()。这个方法有三个参数:

  1. ClassLoader对象,用于指定动态代理类的ClassLoader,一般使用被代理对象的ClassLoader
  2. Class<?>[]对象数组,用于指定被代理类实现的接口;
  3. InvocationHandler对象,用于指定动态代理对象的方法调用处理器。

InvocationHandler接口是一个函数式接口,它只有一个invoke()方法,用于处理动态代理类的方法调用。invoke()方法有三个参数:

  1. Object对象,表示被代理对象;
  2. Method对象,表示方法对象;
  3. Object[]数组,表示方法参数。

当动态代理类的方法被调用时,JVM会自动调用代理对象的invoke()方法,将方法名、方法参数等作为参数传入该方法。在invoke()方法中,我们可以通过反射机制执行被代理类中的相应方法,并对方法的返回值进行处理和返回。

总体来说,JDK动态代理是在运行时动态生成一个类,并在该类中实现代理接口中的方法。当该类的方法被调用时,JVM会调用invoke()方法,从而实现代理方法的处理和返回。

执行测试:

 这样的话后续再新增新的业务方法时只需要进行接口方法的核心业务的书写,而不需要再关注非核心业务代码的处理,非核心业务的代码统一在代理对象中处理即可

cglib动态代理

CGLib 动态代理的实现原理主要是利用 ASM 字节码操作库和 Java 反射机制,在程序运行时动态地生成一个新类。这个新类继承自被代理的类,并覆盖掉所有非 final 方法,然后在这些方法中插入额外的操作(如日志记录、权限验证、事务控制等),达到动态代理的目的。 CGLib 通过子类化的方式来实现代理,所以它只能代理出接口的实现类,而不能直接代理接口。CGLib 使用 ASM 框架直接读取 Class 文件,并对其进行转换,从而生成所需的子类,生成的代理对象可以直接访问到被代理类的所有属性和方法。而且由于它是子类化的,所以即使是没有接口的类也可以代理。因此,CGLib 动态代理的应用范围更加广泛。 由于 CGLib 实现的是通过字节码技术产生的子类来实现代理行为,所以代理速度更快,但也存在一定的局限性,例如被代理类不能是 final 类型的、代理的目标方法不能是 final 的等。

下面用cglib来实现前面的示例

 执行测试:

注解实现Aop 

添加必须依赖

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version>
</dependency>

添加Atm类 (主业务逻辑代码块)

 定义打印log方法(提取公共代码逻辑块)

启用代理 

测试:

 

切点表达式

Aop通知类型 

前置通知(@Before)

在连接点方法执行之前的增强处理

前面演示的demo就是使用的前置通知@before,这里不再演示

后置通知(@After)

在连接点方法执行之后的增强处理,无论正常结束还是异常结束,都会执行的处理

调整atm方法

添加后置执行方法

执行测试:

手动调整异常再进行测试

正常结束通知(@AfterReturning)

在连接点方法正常结束后会进行的处理   如果方法有返回值,可以拿到方法的返回值

添加正常结束通知

刚才前面的例子中我们传入参数100时是手动定义的一个异常,那么这里添加一个正常结束通知不会执行才对,测试看下

 调整参数,不抛出异常观察正常通知是否执行

获取正常通知参数

 可以看到这里的方法是有返回值,可以通过正常通知来获取该返回值,从而做进一步的业务处理

再执行测试

异常结束通知(@AfterThrowing)

在连接点方法异常结束后会进行的处理  可以获取异常的信息

添加异常结束通知方法

此时先执行一个不会抛异常的方法观察异常结束通知会不会执行

可以看到正常结束通知执行了,异常结束通知没有执行

调整参数为100的异常执行,查看异常通知方法的执行情况

 可以查看到异常结束通知执行,正常结束通知没有执行

获取异常信息

执行异常测试

 注意此处的异常信息只是捕获到了,没有做任何的处理

环绕通知

通过代码调用方法,在方法的执行周围进行增强

先注释掉之前的通知方法

添加环绕通知

先进行异常测试

进行正常结束测试

 注意:

当有前置后置以及环绕通知时,先进行环绕通知,在方法的具体执行前后进行增强

放开所有通知方法进行测试

注意观察通知执行的顺序

 切面的优先级

当我们的程序中定义了多个切面时,可以通过@Order(数字)来控制各个切面的执行顺序,其中数字越小,执行优先级越高

话不多说,直接上代码

在之前原先的基础上再定义一个切面类

日志信息也稍作调整以做区分,Order设为1,

原先的log切面Order设置为2

 启动测试查看执行优先级

可以观察到优先级顺序

 Aop使用注意点

方法权限不能是private

连接点方法不能是private,会导致Aop不能进行增强

前面举例时的take是public的aop可以进行正常增强,那么如果调整为private,再进行测试看看:

测试 

 Aop增强失效

如果是protected呢

protected也可以进行aop增强

其他方法在内部被调用时不会被增强

直接上代码,这里直接调用两个方法来进行增强

 此时两个方法都被增强

如果在取钱方法中调用了存钱方法,观察此时的增强通知会执行几次

测试

 可以看到增强通知只执行了一次,且只执行了取钱方法的增强通知

注解实现Aop

基于注解实现服务层打印入参和返回参数日志

在业务开发中我们有时需要通过日志打印入参参数和方法返回,但是基本传统写法都是在方法中自定义log日志,这样写其实并不太优雅,可以通过aop进行优化日志打印

未使用Aop效果

新建两个实体模拟存储保存订单Do和更新订单Do

创建服务层模拟业务

 调用接口查看打印日志

可以看到只是执行了服务层的主业务核心代码System.out.println模拟的业务代码,如果还想打印传参和返回值信息就需要使用日志打印log.info("日志信息")等

可以使用Aop进行业务优化

使用注解实现Aop入参返回值等日志打印

新建切面注解

 新建统一转换参数

新建saveOrder和updateOrder转换Operate

 

定义主要切面类

import cn.hutool.json.JSONUtil;
import com.example.demo23.demos.web.annotation.MyLogOperate;
import com.example.demo23.demos.web.service.Convert;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;@Component
@Aspect
public class LogAsept {// 定义切入点@Pointcut("@annotation(com.example.demo23.demos.web.annotation.MyLogOperate)")public void pointcut(){}private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,1,1,TimeUnit.SECONDS,new LinkedBlockingDeque<>());//环绕通知@Around("pointcut()")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{Object obj = proceedingJoinPoint.proceed();threadPoolExecutor.execute(()->{try{MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();MyLogOperate myLogOperate = methodSignature.getMethod().getAnnotation(MyLogOperate.class);Class<? extends Convert> convert = (Class<? extends Convert>) myLogOperate.convert();Convert logConvert = convert.newInstance();OperateLogDo operateLogDo = logConvert.convert(proceedingJoinPoint.getArgs()[0]);operateLogDo.setDesc(myLogOperate.desc()).setResult(obj.toString());System.out.println("插入 operateLog" + JSONUtil.parseObj(operateLogDo));}catch (InstantiationException ex) {throw new RuntimeException(ex);} catch (IllegalAccessException ex) {throw new RuntimeException(ex);}});return obj;}
}

服务层添加注解使用aop进行日志切入

启动测试:

切入成功,打印入参和方法返回值成功

 还可以再详细一些打印出接口的调用时间,方法,路径等

示例源码

需要源码的伙伴在下面自取即可

链接:aop示例源码 
提取码:z2wp 

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

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

相关文章

树莓派上使用Nginx通过内网穿透实现无公网IP访问内网本地站点

前言 安装 Nginx&#xff08;发音为“engine-x”&#xff09;可以将您的树莓派变成一个强大的 Web 服务器&#xff0c;可以用于托管网站或 Web 应用程序。相比其他 Web 服务器&#xff0c;Nginx 的内存占用率非常低&#xff0c;可以在树莓派等资源受限的设备上运行。同时结合c…

XTU OJ 1146 矩阵乘法学习笔记

原题 题目描述 给你两个矩阵A(n*k),B(k*m),请求A*B。 输入 第一行是一个整数K&#xff0c;表示样例的个数。 每个样例包含两个矩阵A和B。 每个矩阵的第一行是两个整数n,m,(1≤n,m≤10)表示矩阵的行和列 以后的n行&#xff0c;每行m个整数&#xff0c;每个整数的绝对值不超过…

如何让大模型更好地完成知识图谱推理?

​ 论文标题&#xff1a; Making Large Language Models Perform Better in Knowledge Graph Completion 论文链接&#xff1a; https://arxiv.org/abs/2310.06671 代码链接&#xff1a;GitHub - zjukg/KoPA: [Paper][Preprint 2023] Making Large Language Models Perform Be…

node-red - 节点实战总结1

node-red - 节点实战总结1 二、功能2.1 循环(for\while) 三、网络四、序列五、解析六、存储七、协议7.1 modbus协议7.2 opcua 八、formats8.1 时间格式化与时区转换 二、功能 2.1 循环(for\while) 安装节点node-red-contrib-loop-processing,该节点支持三种方式的循环&#xf…

【SpringBoot】 This application has no explicit mapping for 解决方法

This application has no explicit mapping for 解决方法 This application has no explicit mapping for 解决方法一、背景二、原因三、解决方案方式一&#xff1a;方式二&#xff1a; 四、解决 This application has no explicit mapping for 解决方法 一、背景 在SpringBo…

奥特曼不是第一次被开除!离职YC系“被创始人要求离开”

明敏 西风 发自 凹非寺 量子位 | 公众号 QbitAI 钮祜禄奥特曼&#xff0c;竟然不是第一次被“扫地出门”&#xff1f;&#xff1f;&#xff01; 没想到&#xff0c;OpenAI闹剧刚稍微消停了一点&#xff0c;“前传”马上来了。 《华盛顿邮报》从知情人士处获悉&#xff0c;奥…

java编程:使用递归 循环和位运算实现将10进制转为2进制

1 递归 /*** 递归&#xff1a;十进制转二进制* param decimal 待转换的十进制数* param binary 转换后的二进制数*/public static void decimalToBinaryByRecursion(int decimal,StringBuilder binary){if(decimal < 0){return;}decimalToBinaryByRecursion(decimal/2,bina…

3D卷积的理解

卷积核不仅需要在高宽这两个维度上进行滑动&#xff0c;还需要在时间维度上进行滑动

前端设计问题:iframe

居中问题&#xff1a; 尝试了一般的居中方法&#xff0c;无效果 display: flex;justify-content: center;align-items: center;放到导航栏下面不居中 放到页面底部还是不居中 Code <iframe id"demo_sanshui" src"demo_sanshui.html" width"120%…

【现场问题】现场的zk出现问题,ES也出现问题,一个一个排查出来,服务器重启了

湖南现场 zk出现问题ES出现问题了罪魁祸首&#xff0c;服务器重启 zk出现问题 发现集群出现问题了&#xff0c;想都没想就直接去重启了&#xff0c;把三台服务器都重启 ES出现问题了 三台机器只有一台机器是有ES的&#xff0c;但是看了配置文件&#xff0c;发现这个ES是三台…

centos7 openssh版本升级至 openssh-9.5p1

公司项目验收提示ssh版本存在漏洞&#xff0c;要求升级至最高版本&#xff0c;这里做个记录 默认版本 [rootlocalhost ~]# sshd -v unknown option -- v OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017yum groupinstall -y "Development Tools" yum install -y …

[HCIE] IPSec-VPN (IKE自动模式)

概念&#xff1a; IKE&#xff1a;因特网密钥交换 实验目标&#xff1a;pc1与pc2互通 步骤1&#xff1a;R1与R3配置默认路由 R1&#xff1a; ip route-static 0.0.0.0 0.0.0.0 12.1.1.2 R2&#xff1a; ip route-static 0.0.0.0 0.0.0.0 23.1.1.2 步骤2&#xff1a;配ACL…

Postgresql在ubuntu 22.04上遭遇OOM的处理方法

OOM机制就是kill那些占用内存多且优先级低的进程以此来保证操作系统内核的正常运转&#xff0c;一旦我们关闭OOM可能会导致操作系统内核奔溃。 https://manpages.ubuntu.com/manpages/jammy/en/man1/choom.1.html Linux kernel uses the badness heuristic to select which pro…

工业级5G路由器:稳定性更高,网络速度更快!

随着5G技术的发展&#xff0c;5G路由器也越来越受到人们的关注。特别是工业级5G路由器&#xff0c;它的应用范围更广&#xff0c;稳定性更高&#xff0c;网络速度更快&#xff0c;已成为许多企业和工业领域的必备选择。 一、工业级5G路由器的特点 工业级5G路由器具有很多独特的…

利用MATLAB进行矩阵运算

一、画出y1/(x3)的函数曲线&#xff0c;x∈[0, 200]。 程序&#xff1a; x0:0.01:200; y(3x).^(-1); plot(x,y) 结果&#xff1a; 二、生成一个信号&#xff1a;xsin(2*pi*t)cos(4*pi*t) 程序&#xff1a; syms t; xsin(2*pi*t).*cos(4*pi*t); fplot(x,[0 pi]); 结果&…

MyBatis - 自定义 ResultMap 返回数据与数据库查询不一致

问题描述 最近遇到一个查询列表问题&#xff0c;发现实际数据库查询 4 条数据&#xff0c;但是经过程序就是 3 条&#xff0c;一开始怀疑是不是自己程序做了去重啥的&#xff0c;一顿排查猛如虎发现并没有&#xff0c;后来看了下 resultMap 的机制的坑~ <resultMap id"…

electerm 跨平台的终端 /ssh/sftp 客户端

文章目录 electerm功能特性主题配色 electerm 每个程序员基本都离开SSH链接工具,目前市场上好用的基本都是收费的 给大家推荐一款国人开发的开源链接工具https://github.com/electerm/electerm 到目前为止star已经9.5K了,非常受欢迎 功能特性 支持ssh,telnet,serialport,本地和…

使用AndResGuard报错:copy res file not in resources.arsc file:Ezi.xml

Android使用AndResGuard进行资源混淆&#xff0c;压缩。 源码地址&#xff1a;GitHub - shwenzhang/AndResGuard: proguard resource for Android by wechat team 集成完成后编译过程中出现如下错误&#xff1a; 14:57:05 copy res file not in resources.arsc file:IUk.xml…

CMake API使用指南

文章目录 CMake 的基本语法和用法1. CMakeLists.txt 基本结构2. 变量和宏3. 条件语句4. 循环语句5. 定义和使用函数6. 导入库和链接库7. 设置编译器选项 message1. 显示普通消息&#xff1a;2. 显示带模式的消息&#xff1a;3. 显示变量值&#xff1a;4. 显示多行消息&#xff…

ptpd2提示failed to join the multicast group (strerror: No buffer space available)

下载交叉编译ptpd-ptpd-2.3.1源码&#xff0c;在IMX6板子上面运行ptpd2提示错误如下&#xff1a; rootimx6qsabresd_genvict:~# ./ptpd2 -C -m -i eth0 2023-11-24 14:30:21.484399 ptpd2[6512].startup (info) (___) Configuration OK 2023-11-24 14:30:21.487152 ptpd2…