AspectJ入门(二)— 应用

news2024/11/27 8:34:13

 AspectJ便于调试、测试和性能调整工作。定义的行为范围从简单的跟踪到分析,再到应用程序内部一致性到测试。AspectJ可以干净地模块化这类功能,从而可以在需要时轻松地启用和禁用这些功能。

1 基础

本节将继续介绍AspectJ到一些基础功能,为后面的应用提供使用基础。

1.1 thisJoinPoint

当前连接点,提供对连接点可用状态及其静态信息的反射访问。

thisJoinPoint分为静态及实例部分。静态部分包含了连接点类型、签名及位置等信息。实例部分包含了连接点所在的this,代理对象及方法参数。

1.1.1 staticPart静态部分

可通过aspectJ变量:thisJoinPointStaticPart(如果只对连接点的静态信息感兴趣,则应通过访问此变量来以获得更佳性能) 或者thisJoinPoint.getStaticPart()获取静态部分。

图 连接点静态部分的方法

getId 方法获取的id是从0开始的。同一个切点下不同的连接点id是从0开始递增的。

图 静态部分代码及运行结果

1.1.2 实例部分的this 与 target

this: 连接点所在的this对象,当此对象不存在时返回空。(不包括静态空间及方法)。

target:目标对象,即代理对象。

我们可以通过连接点的实例来获取this、target及advice的参数。在实际开发中,我们通常不采用这种方式,因为这种方式会更耗时。我们可以通过下面的方式来获取这些参数:

public aspect ThisAndTargetAspect {

    after(ThisAndTarget.TestThisAndTarget obj, ThisAndTarget target, String inputStr) returning(String str):
            call(String article.custom.ThisAndTarget.fun1(String))
            && args(inputStr) && target(target) && this(obj){
        System.out.println("参数:" + inputStr);
        System.out.println("返回值:" + str);
        System.out.println("this:" + obj);
        System.out.println("target:" + target);
    }

}

1.2 切点的部分声明关键词

1.2.1 call 与 execution

call: 调用方法的地方。

execution:方法执行的地方。

图 call与execution的演示代码及运行结果

1.2.2 withincode

withincode 指定特定方法作用域内的所有连接点(不包括该方法里所调用方法的相关连接点)。而within则是指定类的所有连接点。

图 withincode 演示代码及运行结果

2 应用

AspectJ 可用于跟踪调试、日志记录及契约约束等场景。在开发中,我们可以通过一个配置文件来控制是否使用AspectJ,从而控制AspectJ模块的插拔。

2.1 跟踪调试

在调试代码过程中,我们需要写好多测试方法来测试某个类的函数,甚至有时需要在被测试的方法中插入些测试代码以获得某些结果值。在测试完后我们需要把这些代码删除。这样容易删除一些业务代码,同时也带来了一定的工作量。

业务上线时我们要把这些测试代码移除,但是有时我们希望保持它们以供下个版本的测试。

使用AspectJ让上面这些需求的实现变得更容易。

public class TestEntity {

    public int fun1(int num1, int num2) {
        if (num2 > 99) num2 = 0;
        return num1 + num2;
    }

    public static void main(String[] args) {
        TestEntity entity = new TestEntity();
        entity.fun1(3,99);
        entity.fun1(63,101);
    }

}


public aspect TestEntityAspect {

    after(int num1,int num2) returning(int sum): call(int article2.custom.TestEntity.fun1(int,int)) && args(num1,num2) {
        System.out.println(thisJoinPoint.getSignature() + "的测试");
        System.out.println("参数是num1:" + num1 + ";num2:" + num2);
        System.out.println("结果是:" + sum);
        int result = num1 + num2;
        System.out.println("预期结果:" + result);
        if (result != sum) {
            throw new RuntimeException(thisJoinPoint.getSignature() + "结果值不对");
        }
    }

}

2.2 日志记录

我们借助log4j等框架记录日志时,通常会在业务代码里插入记录日志的代码。这样让业务代码变得更加繁杂。同时,如果我们想在第三方库的方法中记录日志,平常方法将无法实现。

借助AspectJ我们可以很轻松的记录日志及对第三方库中的方法进行日志记录。

需求:统计LogEntity 的fun方法在fun1中被调用的次数(fun可能在其他方法中也会被调用)。

public class LogEntity {

    public void fun() {
        System.out.println("fun");
    }

    public void fun1() {
        fun();
        System.out.println("fun1");
        fun();
    }

    public void fun2() {
        fun();
        System.out.println("fun2");
        fun();
    }

    public static void main(String[] args) {
        LogEntity logEntity = new LogEntity();
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            int nextInt = random.nextInt(11);
            if (nextInt > 5) logEntity.fun1();
            else logEntity.fun2();
        }
    }

}

public aspect LogEntityAspect {

    private static int count = 0;

    after(): call(void article2.custom.LogEntity.fun()) && withincode(void article2.custom.LogEntity.fun1()) {
        count++;
        System.out.println("被调用次数:" + count);
    }

}

2.3 前置或后置条件

现在好多项目都采用“契约式设计”方法。Design By Contract,简称DbC。这种设计方法要求软件设计者为软件组件定义正式的,准确的并且可验证的接口。

契约式设计的三个部分:

1)前置条件:为了调用函数,必须为真的条件。在其违反时,函数绝不调用。

2)后置条件:函数完成时的状态。确保该状态符合预期结果。

3) 不变式:保证类的状态在任何功能被执行后都保持在一个可接受的状态。

AspectJ 可以很容易编写前置及后置条件。

public class ContractEntity {

    public double division(double num1, double num2) {
        if (num1 > 999) num1 = 0;
        return num1 / num2;
    }

    public static void main(String[] args) {
        ContractEntity entity = new ContractEntity();
        entity.division(34,2);
//        entity.division(42,0);
        entity.division(2134,34);
    }

}

public aspect ContractEntityAspect {

    before(double num1,double num2):call(double article2.custom.ContractEntity.division(double,double )) && args(num1,num2) {
        if (num2 == 0) {
            throw new RuntimeException("被除数不能为0");
        }
    }

    after(double num1,double num2) returning(double res):call(double article2.custom.ContractEntity.division(double,double )) && args(num1,num2){
        String str = "除数:" + num1 + ";被除数:" + num2;
        System.out.println(str);
        double num = num1 / num2;
        System.out.println("预期值:" + num);
        System.out.println("结果:" + res);
        if (num != res) {
            throw new RuntimeException("计算结果有误:" + str);
        }
    }

}

2.4 定义编译器错误

declare error: 切点表达式 : “错误提示”;  定义一个错误,会在代码编译器抛出。

declare error: call(* article.custom.DeclareEntity.fun1(..)): "不能使用该方法";

上面这条语句的含义是:如果在代码中有调用DeclareEntity的fun1方法,那么在编译代码时,将抛出错误“不能使用该方法”。

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

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

相关文章

【量化金融】《证券投资学》吴晓求(第四版)(更新中)

这里写目录标题 第一篇 基本知识第1章 证券投资工具名词解释简答题 第2章 证券市场名词解释简答题 第二篇 基本分析第三篇 技术分析第四篇 组合管理第五篇 量化分析与交易策略 第一篇 基本知识 第1章 证券投资工具 名词解释 风险&#xff08;risk&#xff09; 未来结果的不…

半年没涨薪了,原来忽略了这个职场技巧

大家好&#xff0c;我是木川 说到职场&#xff0c;大家都想爬得高一些&#xff0c;赚得多一些对吧&#xff1f;这时候&#xff0c;“向上管理”就显得特别重要了。 其实这就是个高级点的说法&#xff0c;意思就是怎么跟老板打好关系&#xff0c;让自己在工作上更顺利。 一、成功…

【KingbaseES】实现MySql函数WEERDAY

CREATE OR REPLACE FUNCTION weekday(date_val date) RETURNS integer AS $$ BEGIN RETURN EXTRACT(ISODOW FROM date_val); END; $$ LANGUAGE plpgsql IMMUTABLE;

从0开始python学习-39.requsts库

目录 HTTP协议 1. 请求 2. 响应 Requests库 1. 安装 2. 请求方式 2.1 requests.请求方式(参数) 2.2 requests.request() 2.3 requests.session().request() 2.4 三种方式之间的关联 3. 请求参数 3.1 params&#xff1a;查询字符串参数 3.2 data&#xff1a;Form表单…

自然语言转SQL,一个微调ChatGPT3.5的实例(下)--模型微调及模型性能

提交训练集进行微调 一旦我们创建了JSONL文件&#xff08;可以在这里或ipfs_here找到一个小样本&#xff09;&#xff0c;下一步是使用以下命令将创建的文件上传到OpenAI&#xff1a; openai.api_key os.getenv("OPENAI_API_KEY") print(openai.File.create(fileo…

Spark内核解析-Spark shuffle6(六)

1、Spark Shuffle过程 1.1MapReduce的Shuffle过程介绍 Shuffle的本义是洗牌、混洗&#xff0c;把一组有一定规则的数据尽量转换成一组无规则的数据&#xff0c;越随机越好。MapReduce中的Shuffle更像是洗牌的逆过程&#xff0c;把一组无规则的数据尽量转换成一组具有一定规则…

mycat 安装和水平分表

1.拉取需要创建docker版的mycat资源 # 下载对应的资源 git clone https://github.com/ruanjiayu/docker.mycat # 进入docker.mycat cd /home/cluster/mycat/docker.mycat # 构建镜像 docker-compose build 2.修改配置 vim config/mycat/schema.xml <?xml version"…

Mac M1 Parallels CentOS7.9 Install Parallels Tools

一、挂载parallels-tools安装包 mkdir /media/cdrom/ mount /dev/cdrom /media/cdrom/ mount: /dev/sr0 写保护&#xff0c;将以只读方式挂载二、GCC升级 yum install -y centos-release-scl yum install -y devtoolset-8-gcc*# 切换当前会话中gcc版本为8 scl enable devtool…

【OJ比赛日历】快周末了,不来一场比赛吗? #01.06-01.12 #10场

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 2024-01-06&#xff08;周六&#xff09; #4场比赛2024-01-07…

Unity3D入门基础知识汇总

1、参考链接 01.游戏引擎是啥玩意&#xff1f;_哔哩哔哩_bilibili 2、unity概念 它是一套具有完善体系与编辑器的跨平台游戏开发工具&#xff0c;也称之为游戏引擎。游戏引擎是指一些编写好的可重复利用的代码与开发游戏所用的各功能编辑器。 3、unity界面 右上边可以切换布局…

图像评价指标PSNR、SSIM、LPIPS、FID(接上篇,这篇主要讲FID)

关于FID的计算&#xff0c;这里我直接使用startGANv2中的计算FID的方法&#xff0c;比较简单&#xff0c;快速。理论部分我就不讲了&#xff0c;网上一搜一大堆&#xff0c;我写的都是干货&#xff08;主要是怕太长了&#xff0c;没人看&#x1f602;&#xff09; 上一篇是关于…

苹果电脑菜单栏应用管理软件Bartender 4 mac软件特点

Bartender mac是一款可以帮助用户更好地管理和组织菜单栏图标的 macOS 软件。它允许用户隐藏和重新排列菜单栏图标&#xff0c;从而减少混乱和杂乱。 Bartender mac软件特点 菜单栏图标隐藏&#xff1a;Bartender 允许用户隐藏菜单栏图标&#xff0c;只在需要时显示。这样可以…

【React系列】网络框架axios库的使用

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. axios库的基本使用 1.1. 网络请求的选择 目前前端中发送网络请求的方式有很多种&#xff1a; 选择一:传统的Aj…

指令周期流程图相关题目

已知CPU结构如下图所示&#xff0c;其中包括一个累加器AC、一个状态寄存器和其他几个寄存器。各部分之间的连线表示数据通路&#xff0c;箭头表示信息传递方向。试完成以下工作&#xff1a;①写出图中四个寄存器A、B、C、D的名称和作用&#xff1b;②简述完成指令ADD Y的数据通…

一篇文章学会Vim

一篇文章学会Vim 声明&#xff1a;以下内容均为我个人的理解&#xff0c;如果发现错误或者疑问可以联系我共同探讨 简介 Vim是一个高度可定制的终端文本编辑器&#xff0c;它可以很方便的创建和修改任何类型的文本。作为vi的升级版&#xff0c;有许多新的特性(以下列出的特性…

C# 使用Microsoft消息队列(MSMQ)

写在前面 Microsoft Message Queuing (MSMQ) 是在多个不同的应用之间实现相互通信的一种异步传输模式&#xff0c;相互通信的应用可以分布于同一台机器上&#xff0c;也可以分布于相连的网络空间中的任一位置。 使用消息队列可以实现异步通讯&#xff0c;无需关心接收端是否在…

CentOs搭建Kafka集群

Centos7搭建Kafka集群 一、集群规划二、环境准备三、安装kafka集群1、下载kafka安装包2、解压3、配置环境变量4、编辑配置文件①修改broker.id②配置kafka运行日志路径③配置Zookeeper集群地址 5、启动集群6、测试kafka①、创建topic②、查看当前服务器中的所有topic③、生产者…

算法导论复习——CHP16 贪心算法

定义 每一步都做出当前看来最优的操作。 问题引入——活动选择问题 问题描述 活动选择问题就是对给定的包含n个活动的集合S&#xff0c;在已知每个活动开始时间和结束时间的条件下&#xff0c;从中选出最多可兼容活动的子集合&#xff0c;称为最大兼容活动集合。 不失一般性&a…

Ps 滤镜:极坐标

Ps菜单&#xff1a;滤镜/扭曲/极坐标 Filter/Distort/Polar Coordinates 极坐标 Polar Coordinates滤镜可用来进行平面坐标&#xff08;笛卡尔坐标&#xff09;和极坐标之间的相互转换&#xff0c;从而将矩形图像转换为圆形图像&#xff0c;或者将圆形图像转换为矩形图像。 平面…

安装extiverse/mercury时报错

问题描述 作者在安装 Flarum 的插件 extiverse/mercury 时报错&#xff0c;内容如下图所示 解决方案 ⚠警告&#xff1a;请备份所有数据再进行接下来的操作&#xff0c;此操作可能会导致网站不可用&#xff01; 报错原因&#xff1a;主要问题是在安装过程中解决依赖关系。具…