AspectJ 对于 AOP 的实现

AspectJ 简介

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

这是百度百科中对 AspectJ 的介绍。

通知类型

在 spring 中,定义了四种通知类型,前置通知、后置通知、环绕通知、异常通知,在 AspectJ 中,多了一种,最终通知,无论程序执行是否正常,该通知都会被执行,类似于 Java 中的 try...catch...finally 中的 finally 代码块的执行。其中每一种通知类型都对应一个注解。

  • 前置通知  @Before
  • 后置通知  @AfterReturning
  • 环绕通知  @Around
  • 异常通知  @AfterThrowing
  • 最终通知  @After

切入点表达式

在 AspectJ 中定义了专门用来匹配目标方法的切入点表达式,原型如下:

execution([访问权限类型] 返回值类型 [全限定性类名] 方法名称(参数名称) [抛出异常类型]) ,可以看到,execution() 括号中的就是方法签名,其中 [] 中的是可以省略的。并且在切入点表达式中,支持通配符匹配。

  • *  0个或多个字符
  • ..  用在方法参数中,表示任意多个参数,用在包名中,表示当前包及其子包
  • +  用在类名后,表示当前类及其子类,用在接口后,表示当前接口及其实现类 

spring 引入 AspectJ

我们知道,AOP 是一种编程思想,可以有多种实现,前面的文章 spring 中自动代理生成器的实现 介绍了 spring 对于 AOP 的实现。 AspectJ 也实现了 AOP,通过切入点表达式,可以更方便的匹配到要代理的方法,所以 spring 框架也引入了这种实现。具体的实现方式,共有两种,分别是基于注解的 AOP 实现和基于 xml 的 AOP 实现,各对应一个代理生成器。

  • 基于注解:AnnotationAwareAspectJAutoProxyCreator
  • 基于 xml:AspectJAwareAdvisorAutoProxyCreator

下面先来看看 spring 中 AspectJ 基于注解的 AOP 实现。

基于注解的 AOP 实现

先来定义业务类:

public class UserServiceImpl implements UserService {@Overridepublic void doSome() {System.out.println("do some");}@Overridepublic void doOther() {System.out.println("do other");}@Overridepublic String doThird() {System.out.println("do third");return "aaa";}
}

需要一个切面类,如下:

@Aspect
public class MyAspect {@Before("execution(* *..UserServiceImpl.doSome())")public void beforeSome() {System.out.println("前置增强");}@AfterReturning("execution(* *..UserServiceImpl.doThird())")public void afterReturning() {System.out.println("后置增强");}
}

注册:

<!--配置目标对象-->
<bean id="myUserService" class="com.icheetor.aop.service.impl.UserServiceImpl"/>
<!--配置切面-->
<bean id="myAspect" class="com.icheetor.aop.aspect.MyAspect"/>
<!--配置自动代理-->
<!--底层由AnnotationAwareAspectJAutoProxyCreator实现-->
<aop:aspectj-autoproxy/>

这样,就实现了基于注解的 AOP。

基于 xml 配置的 AOP 实现

AspectJ 除了提供注解方式的 AOP 实现,还提供了 xml 配置方式的实现。

业务类:

public class UserServiceImpl implements UserService {@Overridepublic void doSome() {System.out.println("do some");}@Overridepublic void doOther() {System.out.println("do other");}@Overridepublic String doThird(String bb) {System.out.println("do third");return bb + "aaa";}
}

切面类:

public class MyAspect {public void beforeSome() {System.out.println("前置增强");}public void afterReturning() {System.out.println("后置增强");}
}

此处为丰富应用,还定义了一个 Advice,如下:

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("执行前置通知:" + target.getClass().getName() + "#" + method.getName());}
}

下面来看下在 xml 中的配置:

<!--配置目标对象-->
<bean id="myUserService" class="com.icheetor.aop.service.impl.UserServiceImpl"/>
<bean id="myMethodBeforeAdvice" class="com.icheetor.aop.advice.MyMethodBeforeAdvice"/>
<!--配置切面-->
<bean id="myAspect" class="com.icheetor.aop.aspect.MyAspect"/><!--配置自动代理-->
<!--底层由AspectJAwareAdvisorAutoProxyCreator实现-->
<aop:config proxy-target-class="false" expose-proxy="false"><aop:pointcut id="doSomePointcut" expression="execution(* *..UserServiceImpl.doSome())"/><aop:pointcut id="doThirdAfterReturning" expression="execution(* *..UserServiceImpl.doThird(..))"/><!--advisor 标签需配置在 aspect 之前,由标签顺序而定,详见 org.springframework.aop.config.spring-aop.xsd--><aop:advisor id="my_advisor" advice-ref="myMethodBeforeAdvice" pointcut-ref="doSomePointcut" order="2"/><aop:aspect id="my_aspect" ref="myAspect" order="1"><aop:before method="beforeSome" pointcut-ref="doSomePointcut"/><aop:after-returning method="afterReturning" pointcut-ref="doThirdAfterReturning"/></aop:aspect>
</aop:config>

通过 <aop:pointcut> 标签来定义切入点。<aop:aspect> 定义具体的织入规则,其子标签定义各种通知类型,每一种通知类型对应一种标签。

  • 前置通知  <aop:before>
  • 后置通知  <aop:after-returning>
  • 环绕通知  <aop:around>
  • 异常通知  <aop:after-throwing>
  • 最终通知  <aop:after>

通知标签中 method 用来表示匹配到后,执行切面类中的哪个方法去增强,pointcut-ref 用来指定选择哪个切入点去进行匹配。

<aop:config> 标签下还支持 advisor 的配置,advice-ref 指定引用的 advice,即增强方法,pointcut-ref 指定匹配的切入点。

当 <aop:config> 下子标签 <aop:advisor> 和 <aop:aspect> 同时存在时,<aop:advisor> 需位于 <aop:aspect> 之前,这是由 org.springframework.aop.config.spring-aop.xsd 中标签顺序指定的。

还有个 order 属性,用来决定封装拦截器链时的执行顺序,越小的会先执行,如上面示例所示,两个前置通知,myAspect 中的 beforeSome 会先执行,之后才会执行 myMethodBeforeAdvice 中重写的 before 方法。

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

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

相关文章

游戏陪玩系统开发功能需求分析

电竞游戏陪玩系统是一种专门为游戏玩家提供陪伴、指导和互动服务的平台。这类系统通常通过专业的陪玩师&#xff08;也称为陪练师&#xff09;为玩家提供一对一或多对一的游戏陪伴服务&#xff0c;帮助玩家提升游戏技能、享受游戏乐趣&#xff0c;甚至解决游戏中的各种问题。电…

【数据库入门】关系型数据库入门及SQL语句的编写

1.数据库的类型&#xff1a; 数据库分为网状数据库&#xff0c;层次数据库&#xff0c;关系型数据库和非关系型数据库四种。 目前市场上比较主流的是&#xff1a;关系型数据库和非关系型数据库。 关系型数据库使用结构化查询语句&#xff08;SQL&#xff09;对关系型数据库进行…

【2024亚太杯亚太赛APMCM C题】数学建模竞赛|宠物行业及相关产业的发展分析与策略|建模过程+完整代码论文全解全析

第一个问题是&#xff1a;请基于附件 1 中的数据以及你的团队收集的额外数据&#xff0c;分析过去五年中国宠物行业按宠物类型的发展情况。并分析中国宠物行业发展的因素&#xff0c;预测未来三年中国宠物行业的发展。 第一个问题&#xff1a;分析中国宠物行业按宠物类型的发展…

合法三元数量计算

问题描述 小C、小U 和小R 三个好朋友喜欢做一些数字谜题。这次他们遇到一个问题&#xff0c;给定一个长度为n的数组a&#xff0c;他们想要找出符合特定条件的三元组 (i, j, k)。具体来说&#xff0c;三元组要满足 0 < i < j < k < n&#xff0c;并且 max(a[i], a[…

wsl虚拟机中的dockers容器访问不了物理主机

1 首先保证wsl虚拟机能够访问宿主机IP地址&#xff0c;wsl虚拟机通过vEthernet (WSL)的地址访问&#xff0c;着意味着容器也要通过此IP地址访问物理主机。 2 遇到的问题&#xff1a;wsl虚拟机中安装了docker&#xff0c;用在用到docker容器内的开发环境&#xff0c;但是虚拟机…

深入了解 Linux htop 命令:功能、用法与示例

文章目录 深入了解 Linux htop 命令&#xff1a;功能、用法与示例什么是 htop&#xff1f;htop 的安装htop的基本功能A区&#xff1a;系统资源使用情况B区&#xff1a;系统概览信息C区&#xff1a;进程列表D区&#xff1a;功能键快捷方式 与 top 的对比常见用法与示例实际场景应…

如何删除Kafka中的数据以及删除topic

如何删除Kafka数据已经以及删除topic呢&#xff1f; 1、删除数据 先启动Kafka实例 docker exec -it kafka-0 /bin/bash #进去容器 rm -rf /bitnami/kafka/data/* #删除数据 exit #退出如果删除失败&#xff0c;可能是数据不存在于/bitnami/kafka/data&#xff0c;使用 cd /o…

Easyexcel(4-模板文件)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09; 文件导出 获取 resources 目录下的文件&#xff0c;使用 withTemplate 获…

【2024最新】基于springboot+vue的疫情网课管理系统lw+ppt

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

贴代码框架PasteForm特性介绍之image

简介 PasteForm是贴代码推出的 “新一代CRUD” &#xff0c;基于ABPvNext&#xff0c;目的是通过对Dto的特性的标注&#xff0c;从而实现管理端的统一UI&#xff0c;借助于配套的PasteBuilder代码生成器&#xff0c;你可以快速的为自己的项目构建后台管理端&#xff01;目前管…

从 IDC 到云原生:稳定性提升 100%,成本下降 50%,热联集团的数字化转型与未来展望

作者&#xff1a;金峰&#xff08;项良&#xff09;、朱永林、赵世振&#xff08;寰奕&#xff09; 公司简介 杭州热联集团股份有限公司成立于 1997 年 10 月&#xff0c;是隶属杭州市实业投资集团的国有控股公司。公司专业从事国际、国内钢铁贸易黑色大宗商品及产业服务&…

Python Turtle召唤童年:喜羊羊与灰太狼之懒羊羊绘画

Python Turtle召唤童年&#xff1a;喜羊羊与灰太狼之懒羊羊绘画 &#x1f438; 前言 &#x1f438;&#x1f41e;往期绘画&#x1f41e;&#x1f40b; 效果图 &#x1f40b;&#x1f409; 代码 &#x1f409; &#x1f438; 前言 &#x1f438; 小时候&#xff0c;每次打开电视…

SpringBoot学习记录(四)之分页查询

SpringBoot学习记录&#xff08;四&#xff09;之分页查询 一、业务需求1、基本信息2、请求参数3、相应数据 二、传统方式分页三、使用PageHelper分页插件 一、业务需求 根据条件进行员工数据的条件分页查询 1、基本信息 请求路径&#xff1a; /emps 请求方式&#xff1a; …

6. Spring Cloud Gateway网关超详细内容配置解析说明

6. Spring Cloud Gateway网关超详细内容配置解析说明 文章目录 6. Spring Cloud Gateway网关超详细内容配置解析说明前言1 Spring Cloud Gateway 概述1.1 Spring Cloud Gateway网关 的核心功能1.2 Spring Cloud Gateway VS Zuul 的区别1.3 Spring Cloud Gateway 的基本原理1.4 …

远程管理不再难!树莓派5安装Raspberry Pi OS并实现使用VNC异地连接

前言&#xff1a;大家好&#xff01;今天我要教你们如何在树莓派5上安装Raspberry Pi OS&#xff0c;并配置SSH和VNC权限。通过这些步骤&#xff0c;你将能够在Windows电脑上使用VNC Viewer&#xff0c;结合Cpolar内网穿透工具&#xff0c;实现长期的公网远程访问管理本地树莓派…

Centos 8, add repo

Centos repo前言 Centos 8更换在线阿里云创建一键更换repo 自动化脚本 华为Centos 源 , 阿里云Centos 源 华为epel 源 , 阿里云epel 源vim /centos8_repo.sh #!/bin/bash # -*- coding: utf-8 -*- # Author: make.han

【机器学习】回归模型(线性回归+逻辑回归)原理详解

线性回归 Linear Regression 1 概述 线性回归类似高中的线性规划题目。线性回归要做的是就是找到一个数学公式能相对较完美地把所有自变量组合&#xff08;加减乘除&#xff09;起来&#xff0c;得到的结果和目标接近。 线性回归分为一元线性回归和多元线性回归。 2 一元线…

2024年亚太地区数学建模大赛D题-探索量子加速人工智能的前沿领域

量子计算在解决复杂问题和处理大规模数据集方面具有巨大的潜力&#xff0c;远远超过了经典计算机的能力。当与人工智能&#xff08;AI&#xff09;集成时&#xff0c;量子计算可以带来革命性的突破。它的并行处理能力能够在更短的时间内解决更复杂的问题&#xff0c;这对优化和…

STM32F103 GPIO和串口实战

本节我们将会对STM32F103的硬件资源GPIO和串口进行介绍。 一、GPIO 1.1 电路原理图 LED电路原理图如下图所示&#xff1a; 其中&#xff1a; LED1连接到PA8引脚&#xff0c;低电平点亮&#xff1b;LED2连接到PD2引脚&#xff0c;低电平点亮&#xff1b; 1.2 GPIO引脚介绍 STM32…

FileProvider高版本使用,跨进程传输文件

高版本的android对文件权限的管控抓的很严格,理论上两个应用之间的文件传递现在都应该是用FileProvider去实现,这篇博客来一起了解下它的实现原理。 首先我们要明确一点,FileProvider就是一个ContentProvider,所以需要在AndroidManifest.xml里面对它进行声明: <provideran…