Spring详解(七)----AspectJ 实现AOP

2024-08-29 13:08

本文主要是介绍Spring详解(七)----AspectJ 实现AOP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文网址:https://www.cnblogs.com/ysocean/p/7507993.html

AspectJ 实现AOP
目录
1、什么是 AspectJ?
2、切入点表达式
2、Aspect 通知类型
3、AOP具体实例
4、测试异常通知
5、测试环绕通知


上一篇博客我们引出了 AOP 的概念,以及 AOP 的具体实现方式。但是为什么要这样实现?以及提出的切入点表达式到底该怎么理解?
  这篇博客我们通过对 AspectJ 框架的介绍来详细了解。

1、什么是 AspectJ?
  AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,也可以说 AspectJ 是一个基于 Java 语言的 AOP 框架。通常我们在使用 Spring AOP 的时候,都会导入 AspectJ 的相关 jar 包。
在这里插入图片描述

在 spring2.0以后,spring新增了对AspectJ 切点表达式的支持;Aspect1.5新增注解功能,通过 JDK5的注解技术,能直接在类中定义切面;新版本的 spring 框架,也都建议使用 AspectJ 来实现 AOP。所以说在 spring AOP 的核心包 Spring-aop-3.2.jar 里面也有对 AspectJ 的支持。

2、切入点表达式
  上一篇博客中,我们在spring配置文件中配置如下:

<aop:pointcut expression=“execution(* com.ys.aop..(…))” id=“myPointCut”/>
  那么它表达的意思是 返回值任意,包名为 com.ys.aop 下的任意类名中的任意方法名,参数任意。那么这到底是什么意思呢?
  首先 execution 是 AspectJ 框架定义的一个切入点函数,其语法形式如下:
execution(modifiers-pattern? ref-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)类修饰符 返回值 方法所在的包 方法名 方法抛出的异常
  简单点来说就是:
1 语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
  具体解释我们用下面一张思维导图来看:
在这里插入图片描述

注意:如果切入点表达式有多个不同目录呢? 可以通过 || 来表示或的关系。  
<aop:pointcut expression=“execution(* com.ys.Service1.(…)) || execution(* com.ys.Service2.(…))” id=“myPointCut”/>
  表示匹配 com.ys包下的,以 Service1结尾或者以Service2结尾的类的任意方法。
  
  AOP 切入点表达式支持多种形式的定义规则:
1、execution:匹配方法的执行(常用)
execution(public .(…))
2.within:匹配包或子包中的方法(了解)
within(com.ys.aop…*)
3.this:匹配实现接口的代理对象中的方法(了解)
this(com.ys.aop.user.UserDAO)
4.target:匹配实现接口的目标对象中的方法(了解)
target(com.ys.aop.user.UserDAO)
5.args:匹配参数格式符合标准的方法(了解)
args(int,int)6.bean(id)
6对指定的bean所有的方法(了解)
bean(‘userServiceId’)

2、Aspect 通知类型
Aspect 通知类型,定义了类型名称以及方法格式。类型如下:
before:前置通知(应用:各种校验)
在方法执行前执行,如果通知抛出异常,阻止方法运行afterReturning:
后置通知(应用:常规数据处理)
方法正常返回后执行,如果方法中抛出异常,通知无法执行 必须在方法执行后才执行,所以可以获得方法的返回值。
around:环绕通知(应用:十分强大,可以做任何事情) 方法执行前后分别执行,可以阻止方法的执行 必须手动执行目标方法
afterThrowing:抛出异常通知(应用:包装异常信息) 方法抛出异常后执行,如果方法没有抛出异常,无法执行
after:最终通知(应用:清理现场) 方法执行完毕后执行,无论方法中是否出现异常
  这里最重要的是around,环绕通知,它可以代替上面的任意通知。
  在程序中表示的意思如下:
123456789 try{ //前置:before //手动执行目标方法 //后置:afterRetruning} catch(){ //抛出异常 afterThrowing} finally{ //最终 after}
  对应的 jar 包如下:
  在这里插入图片描述

我们可以查看源码:
  
在这里插入图片描述
在这里插入图片描述
3、AOP具体实例
  ①、创建接口
package com.ys.aop; public interface UserService {
//添加 user
public void addUser();
//删除 user
public void deleteUser();}
  ②、创建实现类
package com.ys.aop; public class UserServiceImpl implements UserService{
@Override
public void addUser() {
System.out.println(“增加 User”);
}
@Override
public void deleteUser() {
System.out.println(“删除 User”);
}
}
  ③、创建切面类(包含各种通知)  
package com.ys.aop; import org.aspectj.lang.JoinPoint; public class MyAspect {
/** * JoinPoint 能获取目标方法的一些基本信息

  • @param joinPoint
  • */
  • public void myBefore(JoinPoint joinPoint){
  • 	System.out.println("前置通知 : " + joinPoint.getSignature().getName());    
    
  • }
  • public void myAfterReturning(JoinPoint joinPoint,Object ret){
  • 	System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);    
    
  • }
  • public void myAfter(){ System.out.println(“最终通知”);
  • }
    }
      ④、创建spring配置文件applicationContext.xml
      我们首先测试前置通知、后置通知、最终通知

aop:config <aop:aspect ref=“myAspect”>

<aop:pointcut expression=“execution(* com.ys.aop..(…))” id=“myPointCut”/>

<aop:before method="myBefore" pointcut-ref="myPointCut"/>                          
<!-- 3.2后置通知  ,目标方法后执行,获得返回值                
<aop:after-returning method="" pointcut-ref="" returning=""/>                   returning 通知方法第二个参数的名称                通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){                    参数1:连接点描述                    参数2:类型Object,参数名 returning="ret" 配置的        -->        <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />                     <!-- 3.3 最终通知 -->                <aop:after method="myAfter" pointcut-ref="myPointCut"/>                       </aop:aspect>    </aop:config>
  ⑤、测试 @Test public void testAop(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService useService = (UserService) context.getBean("userService"); useService.addUser(); }   控制台打印:   ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190802082245821.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMxMzE3MTY=,size_16,color_FFFFFF,t_70)

注意,后置通知的返回值为 null,是因为我们的目标方法 addUser() 没有返回值。如果有返回值,这里就是addUser() 的返回值。

4、测试异常通知
  目标接口保持不变,目标类我们手动引入异常:
public void addUser() {
int i = 1/0;
//显然这里会抛出除数不能为 0
System.out.println(“增加 User”);
}
  接着配置切面:MyAspect.java
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("抛出异常通知 : " + e.getMessage());
}
  接着在 applicationContext.xml 中配置如下:

<aop:after-throwing method=“myAfterThrowing” pointcut-ref=“myPointCut” throwing=“e”/>
  测试:
@Test
public void testAop(){
String str = “com/ys/execption/applicationContext.xml”;
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean(“userService”); useService.addUser();
}
  控制台打印:
  在这里插入图片描述

5、测试环绕通知
  目标接口和目标类保持不变,切面MyAspect 修改如下:
public class MyAspect {
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println(“前置通知”);
//手动执行目标方法
Object obj = joinPoint.proceed();
System.out.println(“后置通知”);
return obj;
}
}
  applicationContext.xml 配置如下:

<aop:around method=“myAround” pointcut-ref=“myPointCut”/>
  测试:
@Test
public void testAop(){
String str = “com/ys/around/applicationContext.xml”;
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean(“userService”); useService.addUser();
}
  打印结果:
  在这里插入图片描述

那么至此,通过 xml 配置的方式我们讲解了Spring AOP 的配置。下一章将通过注解的方式来实现。

这篇关于Spring详解(七)----AspectJ 实现AOP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117943

相关文章

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

一文详解MySQL如何设置自动备份任务

《一文详解MySQL如何设置自动备份任务》设置自动备份任务可以确保你的数据库定期备份,防止数据丢失,下面我们就来详细介绍一下如何使用Bash脚本和Cron任务在Linux系统上设置MySQL数据库的自... 目录1. 编写备份脚本1.1 创建并编辑备份脚本1.2 给予脚本执行权限2. 设置 Cron 任务2

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间