AspectJ入门(一)

news2024/9/24 3:29:14

 AspectJ是一个面向切面的框架,扩展了Java语言。有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。Spring的AOP底层也是用了这个框架。

AOP可以拦截指定的方法并对方法增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离。

join point

连接点

是在程序中已经定义好的点。

pointcuts

切点

挑选这些连接点及取值。动态影响程序流程。

advice

通知/处理

对连接点进行增强的部分,动态影响程序流程。

inter-type declarations

类系间声明

允许程序员修改程序的静态关系,即程序的类的成员和类之间的关系。

aspects

切面

封装上面这些结构。

表 AspectJ中的相关概念

1 idea 运行AspectJ

1,下载并安装AspectJ编译器。下载连接。

图 Mac系统下安装AspectJ编译器

2,在idea中安装AspectJ及AOP Pointcut Language插件。

图 idea 中安装相关插件

3,在项目中,编译器配置选择AJC。

图 Java编译器配置

4,添加AspectJ依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.6</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>

5,创建Aspect文件,Aspect的大致语法和Java一样。(如果在点击new时没有发现Aspect选项,则选择“File”类型,并把后缀改为.aj。)

图 点击new时可创建的文件类型部分截图

2 pointcuts

切点是用来挑选连接点的。

call(void article.service.ShopService.showGoods(String)):表示service包下的ShopService类,方法名为showGoods,有一个String类型参数,返回值为void方法的切点。

切点还可以使用逻辑运算符(&&,||及!)及通配符表示:

before():call(void article.service.ShopService.showGoods(String)) || call(void article..say*(..)) {
    System.out.println("这是一个通知");
}

表示service包下的ShopService类,方法名为showGoods,有一个String类型参数,返回值为void的方法或者是article包下,方法名以say开头,返回值为void的方法的切点。

2.1 命名切点

命名切点格式为:pointcut 切点名():切点表达式

public aspect ShopAspect {

    pointcut shopPointcut(): call(void article.service.ShopService.showGoods(String)) || call(void article..say*(..));

    before():shopPointcut() {
        System.out.println("这是一个通知");
    }
}

2.2 引入与织入

引入,introduction,向现有的类添加新的方法或者属性。

织入,weaving,把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。

图 切面的目标对象类的反编译代码

2.3 获取程序流中的所有连接点 cflow

cflow获取特定连接点之后在程序控制流程内遇到的所有连接点。(每行代码编译后的字节码都属于连接点)

cflowbelow与cflow用法是一样的,唯一的区别是cflowbelow不包括初始连接点。

public aspect SimpleAspect {
    before():cflowbelow(call(* article.flow.AObject.methodA())) && !within(SimpleAspect) {
        System.out.println("连接");
    }
}

public class AObject {
    public static void methodA() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        AObject.methodA();
    }
}
//运行结果
//连接A
//连接A
//连接A
//hello

3 Advice

通知是增强指定连接点(目标方法)的代码片段。

before()

在目标方法调用之前执行。

after()

在目标方法返回或异常后调用。

after() returning:

在目标方法返回后调用。

after() throwing:

在目标方法异常后调用。

around

会将这个目标方法封装起来。

表 通知的5种位置

public aspect AdviceAspect {

    after() throwing: call(void article.service.AdviceService.methodThrowing(..)) {
        System.out.println("methodThrowing通知");
    }
}

public class AdviceService {

    public void methodThrowing() {
        System.out.println("开始执行方法");
        throw new RuntimeException();
    }

    public static void main(String[] args) {
        AdviceService adviceService = new AdviceService();
        adviceService.methodThrowing();
    }
}

图 运行结果

3.1 从切点中获取上下文信息

通知可以从切点那获取并使用连接点的方法参数和目标对象等上下文信息。

public aspect ContextAspect {
    after(ContextService contextService, String argName, int argNum): call(String article.service.ContextService.contextInfo(String,int))
    && args(argName,argNum) && target(contextService){
        System.out.println("织入:argName:" + argName + ";argNum:" + argNum);
        System.out.println(contextService);
    }
}

public class ContextService {
    public String contextInfo(String name, int num){
        System.out.println("hello:" + name + "," + num);
        return "temp";
    }

    public static void main(String[] args) {
        ContextService contextService = new ContextService();
        contextService.contextInfo("word",999);
    }
}

使用命名切点时,如果需要在通知中获取上下文,则需要在命名切点调用时指出这些参数名。

public aspect ContextAspect {

    pointcut argPoint(ContextService contextService, String argName, int argNum): call(String article.service.ContextService.contextInfo(String,int))
            && args(argName,argNum) && target(contextService);

    after(ContextService contextService, String argName, int argNum): argPoint(contextService,argName,argNum){
        System.out.println("织入:argName:" + argName + ";argNum:" + argNum);
        System.out.println(contextService);
    }
}

4 类型间声明

AspectJ可以静态改变类的结构(新增方法、成员变量及构造函数),也可以更改类之间的继承关系。

需求:对于已经写好的Shop类,我们希望通过AspectJ增加记录访客信息及对每位客户到店进行提醒的功能。

public aspect ShopAspect {

    public List<String> Shop.visitInfos = new ArrayList();

    public static void addInfo(Shop shop,String info) {
        shop.visitInfos.add(info);
    }

    before(Shop shop,String customName,String gender):call(void article.entity.Shop.visit(String,String)) && args(customName,gender) && target(shop){
        System.out.println("欢迎光临:" + customName);
        String info = "姓名:" + customName + ";性别:" + gender + ";到访时间:" + new Date();
        addInfo(shop,info);
    }

    after(Shop shop): call(void article.entity.Shop.summary()) && target(shop){
        System.out.println(shop.visitInfos);
    }
}

public class Shop {

    public void visit(String customName,String gender) {
        System.out.println(customName + "进入店铺");
    }

    public void summary() {
        System.out.println("店铺一天总结。");
    }

    public static void main(String[] args) throws InterruptedException {
        Shop shop = new Shop();
        shop.visit("黄先生","男");
        Thread.sleep(1000*10);
        shop.visit("刘女士","刘女士");
        shop.summary();
    }
}

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

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

相关文章

PortSwigger Access Control

lab1: Unprotected admin functionality 访问robots.txt 进了删除即可 lab2: Unprotected admin functionality with unpredictable URL 访问admin-d0qwj5 lab3: User role controlled by request parameter 发现Cookie中存在判断是否为admin lab4: User role can be modifie…

C#教程(五):枚举

1、什么是枚举 枚举&#xff08;Enum&#xff09;是一种用于定义命名常量集合的数据类型。它允许开发人员创建一个命名的整数常量集合&#xff0c;这些常量可以在代码中代表特定的值。 2、示例 以下是一个简单的枚举示例&#xff1a; // 定义一个枚举类型 enum DaysOfWeek …

9道软件测试面试题,刷掉90%的测试程序员

经历了“金9银10”&#xff0c;转眼2024年招聘季就要来了&#xff0c;没点真本事真技术&#xff0c;没点面试经验&#xff0c;不了解点职场套路&#xff0c;如何过五关斩六将&#xff1f;如何打败面试官&#xff1f;如何拿下那梦寐以求的offer&#xff1f; 如果你的跳槽意向已…

8.15 PowerBI系列之DAX函数专题-找出无购买行为的客户

需求 实现 isempty var v_table1 filter(产品表,产品表[商品类别]"furniture") var v_table2 filter(产品表,产品表[商品类别]"XXXX") return isempty(v_table1) //return isempty(v_tabble1) //检查表是否为空 // return countrows(v_table1) //返回非…

50个免费的 AI 工具,提升工作效率(附网址)

上次我们已经介绍了20个精选的提高工作效率的免费AI工具&#xff0c;但如果你觉得这些AI工具还不过瘾的话&#xff0c;想进一步成为职场中最了解AI的人&#xff0c;本文将汇总介绍免费最新的50个AI工具。 DeepSwap DeepSwap 是一个基于 AI 的工具&#xff0c;适用于想要制作令人…

2023航天推进理论基础考试划重点(W老师)绪论固体推进剂

1、推进系统的分类&#xff1a; 按工作原理分&#xff0c; 直接反作用发动机(喷气发动机) 火箭发动机、组合发动机、冲压发动机、涡轮喷气发动机、涡轮风扇发动机 间接反作用发动机 活塞式发动机、涡轮螺旋桨发动机、涡轮轴发动机、航空电动机 2、后面不细讲的火箭发动机要…

数据通信网络基础华为ICT网络赛道

目录 前言&#xff1a; 1.网络与通信 2.网络类型与网络拓扑 3.网络工程与网络工程师 前言&#xff1a; 数据通信网络基础是通信领域的基本概念&#xff0c;涉及数据传输、路由交换、网络安全等方面的知识。华为ICT网络赛道则是华为公司提出的一种技术路径&#xff0c;旨在通…

ts相关笔记(extends、infer、Pick、Omit)

最近刷了本ts小册&#xff0c;对一些知识点做下笔记。 extends extends 是一个关键字&#xff0c;用于对类型参数做一些约束。 A extends B 意味着 A 是 B 的子类型&#xff0c;比如下面是成立的 ‘abc’ extends string599 extends number 看下面例子&#xff1a; type …

枚举(蓝桥杯备赛系列)acwing版

枚举 前言 hello&#xff0c;大家好&#xff0c;前面一段时间已经是把acwing Linux基础课讲完了&#xff0c;其实那些内容完全可以带领小白入门Linux我说过如果有人留言要Linux和Windows server 配置DNS Web ftp 的内容我就做一期&#xff0c;但是没人留言我也就先不自作多情了…

ComfyUI激活中文

comfyui中文地址如下&#xff1a; https://github.com/AIGODLIKE/AIGODLIKE-ComfyUI-Translationhttps://github.com/AIGODLIKE/AIGODLIKE-ComfyUI-Translation如何安装&#xff1f; 1. git安装 进入项目目录下的custom_nodes目录下&#xff0c;然后进入控制台&#xff0c;运…

【Flutter】黑白图片

一、将图片处理成黑白图片 //第一种方法CachedNetworkImage(imageUrl: imageUrl,width: 80,height: 80,fit: BoxFit.cover,color: Colors.black,//目标颜色colorBlendMode: BlendMode.color,//颜色混合模式)//第二种方法ShaderMask(shaderCallback: (Rect bounds) {return Lin…

ESP32通过PWM方波驱动蜂鸣器

摘要&#xff1a;本文介绍一下有源蜂鸣器和无源蜂鸣器的区别&#xff0c;然后给出两种驱动蜂鸣器的方式。 从外观上来看&#xff0c;无源蜂鸣器和有源蜂鸣器的区别主要有以下几个方面&#xff1a; 1.无源蜂鸣器比较“矮”&#xff0c;有源蜂鸣器比较“高”&#xff1b; 2.无源…

【方案】如何利用大数据+云计算技术打造智能环境监控系统?

小编在之前的文章中也提到过基于云计算的环境智能监控系统是什么样的&#xff0c;收到了很多朋友的关注&#xff0c;今天小编就再次根据智能监控为切入点&#xff0c;深入讲解智能环境监控系统方案的详细落实。 1、传感器节点&#xff1a;首先需要选择适合应用场景的各类传感器…

【开放集检测】OpenGAN: Open-Set Recognition via Open Data Generation 论文阅读

文章目录 英语积累为什么使用GAN系列网络进行开放集检测摘要1. 前言2. 相关工作开集检测基于GAN网络的开集检测基于暴露异常数据的开集检测 3. OpenGAN3.1 公式建模3.1.1 二分类方法存在问题如何解决 3.1.2 使用合成数据存在问题如何解决 3.1.3 OpenGAN3.1.4 模型验证 3.2 先前…

OpenEuler安装内网穿透工具实现ssh连接openEuler系统

文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 本文主要介绍在openEuler中安装Cpolar内网穿透工具实现远程也可以ssh 连接openEuler系统使用. 欧拉操作系统(openEuler, 简称“欧拉”…

BUUCTF——Reverse——helloword

1、题目 2、工具 JADX-GUI&#xff1a;安卓逆向工具&#xff0c;可以打开.apk、.dex、.jar、.zip等格式的文件。下载地址&#xff1a;JADX download | SourceForge.net 下载的JADX是一个.exe执行文件&#xff0c;打开会自动检查环境&#xff0c;要求有Java环境&#xff0c;点击…

VMware虚拟机安装Ubuntu系统教程

所使用的文件如下&#xff1a; VMware Workstation 17 Pro ubuntu-22.04.3-desktop-amd64.iso 一、ubuntu 命名规则及各版本一览表 1.ubuntu 命名规则&#xff1a; 例如&#xff1a;ubuntu 16.04 LTS 是长期维护版本&#xff1b;ubuntu 17.04 是新特性版本 前两位数字为发…

GaN HEMT的大信号(RF PA)性能

来源&#xff1a;Novel Drain-Connected Field Plate GaN HEMT Designs for Improved VBD −RON Tradeoff and RF PA Performance (IEEE TRANSACTIONS ON ELECTRON DEVICES) 使用 TCAD 提取的 I-V 和 C-V 曲线族&#xff0c;结合 Keysight 的 IC-CAP 器件建模套件和先进SPICE模…

C# WPF上位机开发(MySql访问)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们学习了数据库sqlite&#xff0c;不过这是一种小型的数据库&#xff0c;作为内部使用还可以。但是&#xff0c;如果要与外面的其他供应商进…

overleaf 支持中文

基本操作 左上角menu中&#xff0c;切换compiler 到xelatex。 然后在\documentclass声明下面加一个 \usepackage{ctex}。 使用\usepackage{xecjk}可能也可以&#xff0c;但会有警告。 警告分析 Font “FandolSong-Regular” does not contain requested Script “CJK”。 网上…