对Spring当中AOP的理解

        AOP(面向切面编程)全称Aspect Oriented Programminge

        AOP就是把系统中重复的代码抽取出来,单独开发,在系统需要时,使用动态代理技术,在不修改源码的基础上,将单独开发的功能通知织入(应用)到系统中的过程,完成完整的代码逻辑

        优点:减少重复代码、提高开发效率、提高维护性

AOP相关术语:

        1. Joinnoint(连接点):连接点是指那些被拦截到的点。这些点指的是方法,spring只支持方法类型的连接点。指切面在系统中要应用的位置,spring 中能够使用切面的位置为方法,所以连接指方法连接点指要调用某个方法时拦截到对这个方法的调用,做一些其他事情然后再执行目标方法拦截到的方法就是连接点。

        2. Pointcut(切入点):指我们要对那些Joinpoint进行拦截的定义,spring中使用切入点表达式定义(切入点表达式)简单理解,切入点是对连接点的描述,它将多个连接点进行概括的定义。

        3. Advice(通知):指拦截到joinpoint之后所要做的事情就是通知

         通知:前置通知、后置通知、异常通知、最终通知、环绕通知

        4. Target(目标对象):代理的目标对象

        5. Weaving(织入):将通知应用到切入点的过程

        6.Proxy(代理) :代理对象 

        7. Aspect(切面) :切入点和通知的总称

         简单说AOP是,在系统执行某个方法时,在执行这个方法前或方法后去执行另一段程序(另一段程序就是AOP中的通知),而拦截这个方法的定义可以称为切入点

        

SprinaAOP.的使用步骤(基于注解):
        1.引入spring依赖包和aop.植入依赖包 Aspect Weaver包或者spring-aspects包:

         2.创建切面类
        3.将切面类交个spring进行管理,使用@Component注解
        4.将切面类设置为一个切面,使用@Aspect注解
        5.编写切入点poincut,使用切入点表达式定义连接点(方法)。
        Execution(表达式)
        表达式写法:访问修饰符返回类型包名.包名.类名.方法名(参数列表)//指定那些方法做为切入点(拦截那些方法)

使用具体方法方式:@PointCut( execution(* com.xxx.service.UserService.addUser(..)))

了解更多Execution表达式Introduction to Pointcut Expressions in Spring | Baeldung

        6.编写相关通知

        7.切面源码

       

            在看切面源码前,我们需要提前把所需的环境先准备好,这里看一下我的结构:

        

这块我直接用service包下的UserService接口的addUser()和它的实现类UserServiceImpl来进行体现上述Advice(通知).

先看UserService接口

package com.xxx.service;public interface UserService {public String addUser(int id,String name);public void delUser();
}

UserServiceImpl

package com.xxx.service.impl;import com.xxx.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic String addUser(int id,String name) {System.out.println("UserServiceImpl--------addUser");return "你好:"+name;}@Overridepublic void delUser() {System.out.println("UserServiceImpl--------delUser");}
}

下面我们来看最主要的aspects包下的UserAspects类,该类就是对上述addUser()方法进行前置通知、后置通知、异常通知、最终通知、环绕通知。

首先咱们先看前置通知:

在前置通知前首先我们执行一下程序,结果如下:

然后我们加上前置通知代码后,再看结果:

package com.xxx.aspects;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;@Aspect       //切面注解
@Component    //交给Spring进行控制翻转
@EnableAspectJAutoProxy  //开启spring的切面自动代理功能
public class UserAspects {@Pointcut("execution(* com.xxx.service.UserService.addUser(..))")public void pointCuts() {}/*前置通知*/@Before("pointCuts()")public void beforeAdvice(){System.out.println("前置被通知执行");}
}

 再加上前置通知后,结果如下:

下面我们来看后置通知,通过上述的前置通知,我们可以推断出后置通知应该就是addUser()执行后进行通知的,下面我们来看看是不是这样的。首先和之前一样,加上后置通知的代码:

package com.xxx.aspects;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;@Aspect       //切面注解
@Component    //交给Spring进行控制翻转
@EnableAspectJAutoProxy  //开启spring的切面自动代理功能
public class UserAspects {@Pointcut("execution(* com.xxx.service.UserService.addUser(..))")public void pointCuts() {}/*前置通知*/@Before("pointCuts()")public void beforeAdvice(){System.out.println("前置被通知执行");}/*后置通知*/@AfterReturning("pointCuts()")public void AfterAdvice(){System.out.println("后置被通知执行");}
}

加上后置通知后,运行结果如下:

下面我们来看异常通知,字面意思就是,在程序出现异常的时候就会出现该通知,下面我们就看相关的代码:

package com.xxx.aspects;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;@Aspect       //切面注解
@Component    //交给Spring进行控制翻转
@EnableAspectJAutoProxy  //开启spring的切面自动代理功能
public class UserAspects {@Pointcut("execution(* com.xxx.service.UserService.addUser(..))")public void pointCuts() {}/*前置通知*/@Before("pointCuts()")public void beforeAdvice(){System.out.println("前置被通知执行");}/*后置通知*/@AfterReturning("pointCuts()")public void AfterAdvice(){System.out.println("后置被通知执行");}/*异常通知*/@AfterThrowing("pointCuts()")public void throwAdvice(){System.out.println("异常通知执行");}
}

由于异常通知是在程序出现异常的时候才会执行该通知,那么咱们就给addUser()中来个异常

下面我们来看运行结果:

这儿需要注意的是异常通知和后置通知只能执行其中一个,通知的执行过程类似于下面这种:

下面的最终通知就不写了,它前面所述的其它通知类似,环绕通知就是一个可以做它们4个做的事情,下面直接把源码给出来看一下就行了:

        

package com.xxx.aspects;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;@Aspect       //切面注解
@Component    //交给Spring进行控制翻转
@EnableAspectJAutoProxy  //开启spring的切面自动代理功能
public class UserAspects {@Pointcut("execution(* com.xxx.service.UserService.addUser(..))")public void pointCuts() {}/*前置通知*/@Before("pointCuts()")public void beforeAdvice(){System.out.println("前置被通知执行");}/*后置通知*/@AfterReturning("pointCuts()")public void AfterAdvice(){System.out.println("后置被通知执行");}/*异常通知*/@AfterThrowing("pointCuts()")public void throwAdvice(){System.out.println("异常通知执行");}/*最终通知*/@After("pointCuts()")public void finallyAdvice(){System.out.println("最终通知执行");}/*环绕通知就是可以把上面四个通知都可以实现* */@Around("pointCuts()")public String aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){try {System.out.println("环绕通知----前置被通知执行");String proceeds = (String) proceedingJoinPoint.proceed();return proceeds;} catch (Throwable e) {e.printStackTrace();}return null;}}

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

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

相关文章

git从clone到pr的全流程

在使用 Git 和 GitHub 进行协作时,从克隆(clone)一个仓库到创建拉取请求(Pull Request,简称 PR)的全流程通常包括以下步骤: 1. 克隆远程仓库 首先,你需要将远程仓库克隆到你的本地…

chatgpt搭建

chatgpt两步搭建大法 部署docker环境 下载docker curl -fsSL https://get.docker.com -o get-docker.sh安装docker sh get-docker.sh运行docker服务 systemctl start docker查看运行状态 systemctl status docker设置docker开机自启 systemctl enable docker部署chatgpt…

慎投!这3本期刊诚信风险高,被警告和风险低的期刊选哪个?

近年来,学术界对学术诚信的关注越来越多,期刊的学术诚信风险也日益受到关注。科睿唯安在今年三月份剔除的35本SCI期刊中,绝大多数涉及学术诚信问题!据官方介绍,其已正式开发了一款AI工具,可以锁定存在学术诚…

【JavaScript 基础入门】01 编程语言和计算机基础

编程语言和计算机基础 目录 编程语言和计算机基础1 - 编程语言1.1 编程1.2 计算机语言1.3 编程语言1.4 翻译器1.5 编程语言和标记语言区别1.6 总结 2 - 计算机基础2.1 计算机组成2.2 数据存储2.3 数据存储单位2.4 程序运行 1 - 编程语言 1.1 编程 编程: 就是让计算…

微信小程序(二十二)获取全局实例

注释很详细,直接上代码 上一篇 新增内容: 1.全局实例的定义位置 2.全局实例中数据的修改方法 源码: app.js App({//数据可以包括在第二级globalData:{userInfo:null,token:1243,userInfo:null},//globalData并不是关键词,数据可以…

预制菜春节大洗牌,味知香、千味央厨谁是“硬菜”?

2024年春节预制菜销量走俏,预制菜依然是消费者“年夜饭”上的重头戏。各大生鲜平台、电商、商超、餐饮门店都纷纷开卖春节预制菜。 预制菜赛道两大“玩家”:“预制菜第一股”味知香(605089.SH)、“餐饮供应链第一股”千味央厨(001215.SZ)均在…

jrt运维命令改造

以前发布网站都是定死网站放置路径的,现在JRT想面向更广范围推广,所以就不能明确确定网站放置目录,为此需要改造一下jrt命令和sh来满足目录不确定情况和多个程序用不同管理命令的要求。 以前是写死的,现在改为调程序运行目录的sh…

在Mixamo网站上,下载的模型导入unity后没有材质怎么解决

在Mixamo网站上,下载的模型导入unity后没有材质 1.导入的模型没有材质2.解决方法3.提取后就有材质了 1.导入的模型没有材质 2.解决方法 选中导入的模型 > 选择提取纹理>选择你要提取到的文件夹(默认是当前文件夹)>点击 fix now 3.提取后就有材质了

【漏洞复现】中移铁通禹路由器弱口令漏洞

Nx01 产品简介 中移禹路由器支持宽带拨号、动态IP和静态IP三种上网模式,一般中国移动宽带的光猫都是智能光猫也就是光猫带路由器功能,中移禹路由器作为二级路由使用。 Nx02 漏洞描述 中移禹路由器存在默认口令(admin),攻击者可利用该漏洞获取敏感信息。 Nx03 产品…

《HTML 简易速速上手小册》第7章:HTML 多媒体与嵌入内容(2024 最新版)

文章目录 7.1 在HTML中嵌入视频和音频7.1.1 基础知识7.1.2 案例 1&#xff1a;嵌入视频文件7.1.3 案例 2&#xff1a;嵌入音频文件7.1.4 案例 3&#xff1a;创建一个视频和音频混合的播放列表 7.2 使用 <iframe> 嵌入外部内容7.2.1 基础知识7.2.2 案例 1&#xff1a;嵌入…

算法训练|下一个排列

31. 下一个排列 - 力扣&#xff08;LeetCode&#xff09; 总结&#xff1a;能读懂题目的意思&#xff0c;但是不知道如何下手 题解以及解法&#xff1a; 1、我们需要将一个左边的「较小数」与一个右边的「较大数」交换&#xff0c;以能够让当前排列变大&#xff0c;从而得到…

mysql面试题合集-分布式

前言 前文介绍了MySQL基础知识&#xff0c;现在继续介绍分布式数据库相关知识。 mysql分布式面试题合集 什么是分布式数据库&#xff1f;它与集中式数据库有何不同&#xff1f; 分布式数据库是一种数据库&#xff0c;其中数据和数据库管理系统功能分布在多个相互连接的数据库…

四. 基于环视Camera的BEV感知算法-BEVFormer实战

目录 前言1. BEVFormer实战 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第四章——基于环视Camera的BEV感知算法&#xff0c;一起去学习下 BEVFormer 的相关代码 课程…

Matlab图像平滑滤波学习笔记——卷积、中值滤波、排序滤波以及自适应滤波

1.引言 图像处理是计算机视觉领域中的一个重要分支&#xff0c;其目标是通过对图像进行各种操作来改善图像的质量或提取出特定的信息。在图像处理的诸多任务中&#xff0c;平滑和滤波是常见且关键的操作&#xff0c;用于去除噪声、增强细节或突出图像中的特征。本文将重点介绍…

Groovy语言学习

介绍 Groovy 是一种基于 JVM 的敏捷开发语言&#xff0c;它结合了 Python、Ruby 和 Smalltalk 的许多强大的特性。 Groovy 主要的特点包括&#xff1a; 是一个基于 Java 虚拟机的敏捷动态语言。构建在强大的 Java 语言之上 并添加了从 Python、Ruby 和 Smalltalk 等语言中学…

探索Viper-适用于GoLang的完整配置解决方案

前言 对于现代应用程序&#xff0c;尤其大中型的项目来说&#xff0c;在程序启动和运行时&#xff0c;往往需要传入许多参数来控制程序的行为&#xff0c;我们可以通过命令行参数&#xff0c;环境变量&#xff0c;配置文件等方式来将参数传递给程序。而Viper库为Golang语言开发…

麒麟系统安装minio_centos8.0安装最新minio_离线安装minio并设置权限_创建桶---minio工作笔记001

https://www.minio.org.cn/?id=18&id=3&id=0&id=11&id=9&spinz=qianfeng&adinfo678=baidu&spinz=qianfeng&adinfo678=baidu%3E 首先去到官网去下载minio,然后 可以看到已经显示的官网,然后再去,右边点击下载 进入下载页面一般都是amd64的版本…

如何在事务方法里,执行一段事物提交之后的代码

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){Overridepublic void afterCompletion(int status) {//业务方法}} }); TransactionSynchronizationManager.registerSynchronization有以下的&#xff0c;根据你业务去重写即可 …

【JaveWeb教程】(35)SpringBootWeb案例之《智能学习辅助系统》登录功能的详细实现步骤与代码示例(8)

目录 案例-登录和认证1. 登录功能1.1 需求1.2 接口文档1.3 思路分析1.4 功能开发1.5 测试 案例-登录和认证 在前面的课程中&#xff0c;我们已经实现了部门管理、员工管理的基本功能&#xff0c;但是大家会发现&#xff0c;我们并没有登录&#xff0c;就直接访问到了Tlias智能…

Leetcode3014. 输入单词需要的最少按键次数 I

Every day a Leetcode 题目来源&#xff1a;3014. 输入单词需要的最少按键次数 I 解法1&#xff1a;统计 统计字符串 word 的小写字母个数和 1、#、*、0 的个数。 将小写字母均匀地分配到 8 个按键上&#xff0c;模拟即可。 代码&#xff1a; /** lc appleetcode.cn id3…