Spring 学习(二)AOP
一、什么是AOP
Aspect Oriented Programming,即面向切面编程。对一个大型项目的代码而言,整个系统要求关注安全检查、日志、事务等功能,这些功能实际上“横跨”多个业务方法。在一般的OOP编程里,需要在每一个业务方法内添加相关非业务方法的调用,这实际上是冗余的。如果能够类似IoC一样,这样的安全检查,日志,事务功能单独提取放到外面,核心业务方法不需要关注,就能降低代码耦合度。如果我们以AOP的视角来编写上述业务,可以依次实现:
- 核心逻辑Service
- 切面逻辑,即:
- 权限检查的Aspect;
- 日志的Aspect;
- 事务的Aspect。
然后,以某种方式,让框架来把上述3个Aspect以Proxy的方式“织入”到Service中,这样一来,就不必编写复杂而冗长的Proxy模式
AOP对于解决特定问题,例如事务管理非常有用,这是因为分散在各处的事务代码几乎是完全相同的,并且它们需要的参数(JDBC的Connection)也是固定的。另一些特定问题,如日志,就不那么容易实现,因为日志虽然简单,但打印日志的时候,经常需要捕获局部变量,如果使用AOP实现日志,我们只能输出固定格式的日志,因此,使用AOP时,必须适合特定的场景。
二、AOP
常见的AOP术语包括:
- 切面(Aspect):横跨多个类和方法的模块,定义了一组横切关注点的行为。
- 连接点(Join Point):程序执行过程中可以插入切面的特定点,例如方法调用、异常抛出等。
- 通知(Advice):切面在连接点上执行的行为,包括前置通知、后置通知、环绕通知、异常通知和最终通知等。
- 切点(Pointcut):定义了一组连接点的表达式,用于确定切面在哪些连接点上执行。
- 引入(Introduction):允许向现有类添加新的方法或属性。
- 织入(Weaving):将切面应用到目标对象中,以创建新的代理对象或修改现有对象的字节码。
例如,编写日志loggin切片
@Aspect
@Component
public class LoggingAspect {// 在执行UserService的每个方法前执行:@Before("execution(public * com.itranswarp.learnjava.service.UserService.*(..))")public void doAccessCheck() {System.err.println("[Before] do access check...");}// 在执行MailService的每个方法前后执行:@Around("execution(public * com.itranswarp.learnjava.service.MailService.*(..))")public Object doLogging(ProceedingJoinPoint pjp) throws Throwable {System.err.println("[Around] start " + pjp.getSignature());Object retVal = pjp.proceed();System.err.println("[Around] done " + pjp.getSignature());return retVal;}
}
- @Before()里面的字符串是告诉AspectJ应该在何处执行该方法,这里写的意思是:执行UserService的每个public方法前执行doAccessCheck()代码
- @Around注解,它和@Before不同,@Around可以决定是否执行目标方法
- @Aspect注解,表示它的@Before标注的方法需要注入到UserService的每个public方法执行前,@Around标注的方法需要注入到MailService的每个public方法执行前后
我们需要给@Configuration类加上一个@EnableAspectJAutoProxy注解,Spring的IoC容器看到这个注解,就会自动查找带有@Aspect的Bean,然后根据每个方法的@Before、@Around等注解把AOP注入到特定的Bean中。
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class AppConfig {...
}
三、AOP实现原理
AOP原理实际上就是一个代理类的实现,这个代理是借由Spring容器实现的,例如,将LoggingAspect.doAccessCheck注入UserService的每个public方法中,可以通过如下实现:
public UserServiceAopProxy extends UserService {private UserService target;private LoggingAspect aspect;public UserServiceAopProxy(UserService target, LoggingAspect aspect) {this.target = target;this.aspect = aspect;}public User login(String email, String password) {// 先执行Aspect的代码:aspect.doAccessCheck();// 再执行UserService的逻辑:return target.login(email, password);}public User register(String email, String password, String name) {aspect.doAccessCheck();return target.register(email, password, name);}...
}
容器自动为我们创建了注入了Aspect的子类,取代原始的UserService,并把被@Before @Around关键词修饰的方法覆写。
四、拦截器
AOP拦截器通常是指用于拦截和处理方法调用的组件或类。这些拦截器可以在方法调用前、后或异常抛出时执行特定的逻辑
- @Before:该注解用于定义前置拦截器。在目标方法执行前,被注解的方法将被执行。可以用于实现预处理、参数验证和权限检查等功能。
- @AfterReturning:该注解用于定义后置拦截器。在目标方法成功执行并返回结果后,被注解的方法将被执行。可以用于实现日志记录、结果处理和清理操作等功能。
- @Around:该注解用于定义环绕拦截器。在目标方法执行前后,被注解的方法将被执行。通过在拦截器方法中调用ProceedingJoinPoint.proceed()来控制目标方法的执行,并可以在适当的时机添加额外的逻辑。
- @AfterThrowing:
该注解用于定义异常拦截器。在目标方法抛出异常时,被注解的方法将被执行。可以用于实现异常处理、错误日志记录等功能。
通过使用这些注解,可以将拦截器逻辑与特定的切点(Pointcut)相结合,实现对核心业务逻辑的拦截和处理。可以使用execution()表达式来定义切点,指定要拦截的方法的执行。这些注解可以与Spring AOP的其他功能和配置一起使用,如切面(Aspect)、通知(Advice)和配置文件等,以实现更复杂的AOP编程。
五、注解装配
使用注解装配AOP时,最好需要在被装配的Bean处使用注解标记,被装配的Bean最好自己能清清楚楚地知道自己被安排了。例如,Spring提供的@Transactional。
我们以一个实际例子演示如何使用注解实现AOP装配。为了监控应用程序的性能,我们定义一个性能监控的注解:
@Target(METHOD)
@Retention(RUNTIME)
public @interface MetricTime {String value();
}/**************************************/
@Component
public class UserService {// 监控register()方法性能:@MetricTime("register")public User register(String email, String password, String name) {...}...
}/**************************************/
@Aspect
@Component
public class MetricAspect {@Around("@annotation(metricTime)")public Object metric(ProceedingJoinPoint joinPoint, MetricTime metricTime) throws Throwable {String name = metricTime.value();long start = System.currentTimeMillis();try {return joinPoint.proceed();} finally {long t = System.currentTimeMillis() - start;// 写入日志或发送至JMX:System.err.println("[Metrics] " + name + ": " + t + "ms");}}
}
这段代码中,一直对@Around("@annotation(metricTime)")
存在疑惑,为什么不是MetricTime(类)而是metricTime(参数名),关键在@annotation。
@annotation 是 Spring AOP 中的一个切点指示器,用于匹配被任意注解标记的方法或类。在切点表达式中使用 @annotation(annotationType),其中 annotationType 是要匹配的注解类型,可以是任何有效的注解类型。这个切点指示器的作用是,在切面中匹配被特定注解标记的方法或类,以便在相应的切面方法中对它们进行处理。
以下实例中,@Around(“@annotation(com.example.MyAnnotation)”) 表达式表示匹配被 @MyAnnotation 注解标记的方法。当调用这些被标记的方法时,切面中的 myAdvice 方法会被触发
@Aspect
@Component
public class MyAspect {// 匹配被 @MyAnnotation 标记的方法@Around("@annotation(com.example.MyAnnotation)")public Object myAdvice(ProceedingJoinPoint joinPoint) throws Throwable {// 在方法执行前后执行自定义逻辑// ...return joinPoint.proceed();}}
但在@Around("@annotation(metricTime)")
中,由于切面方法metric要用到被标记注解的实例,而不只是匹配注解类型。那么在 @annotation() 中需要传入该注解的实例。具体来说,如果被切入的方法的参数列表中有一个具有某个特定注解的参数,则可以在切面表达式中使用 @annotation(parameterName) 来匹配并获取该注解的实例。
相关文章:
Spring 学习(二)AOP
一、什么是AOP Aspect Oriented Programming,即面向切面编程。对一个大型项目的代码而言,整个系统要求关注安全检查、日志、事务等功能,这些功能实际上“横跨”多个业务方法。在一般的OOP编程里,需要在每一个业务方法内添加相关非…...
笔记1.1 计算机网络基本概念
计算机网络是通信技术与计算机技术紧密结合的产物 通信系统模型: 计算机网络是一种通信网络 计算机网络是互连的、自洽的计算机集合。 互连:互联互通 自洽:无主从关系 通过交换网络互连主机 Internet:数以百万计的互连的计算设…...
液压切管机配套用液压泵站比例阀放大器
液压切管机配套用液压泵站是液压系统的动力源,可按机械设备工况需要提供一定压力、流量和清洁度的工作介质。它由泵组、油箱组件、控温组件、滤油器组件及蓄能器组件等组合而成,液压泵站主要服务于大型管道工程。...
C++ Primer Plus 第七章笔记
目录 函数基本知识 没有返回值的函数:void函数 有返回值的函数: 函数原型 1.为什么需要函数原型? 2.函数原型的语法 3.函数原型的功能 按值传递函数参数 形参和实参 局部变量 参数问题 使用const指针参数 调用自身的函数…...
常用数据库的 API - 开篇
API API 这个词在大多数人看来可能和 CNS 差不多,前者天天听说就是用不上,后者天天读就是发不了。 不过,通过今天的一个简短介绍,今后 API 这个东西你就用上了,因为在文章最后我将会展示一个最最基础且高频的 API 使…...
C++之生成详细汇编代码(二百一十六)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
AIGC|当一个程序员学会用AI来辅助编程实践
一、辅助编程 作为主要以 JAVA 语言为核心的后端开发者,其实,早些时间我也用过比如 Codota、Tabnine、Github 的 Copilot、阿里的 AI Coding Assistant 等 IDEA 插件,但是我并没有觉得很惊奇,感觉就是生成一些代码片段罢了&#x…...
9.14号作业
仿照vector手动实现自己的myVector,最主要实现二倍扩容功能 有些功能,不会 #include <iostream>using namespace std; //创建vector类 class Vector { private:int *data;int size;int capacity; public://无参构造Vector(){}//拷贝构造Vector(c…...
【面试题】C/C++ 中指针和引用的区别
指针是一个独立的对象,它可以指向不同的变量或对象,可以重新赋值给其他变量。而引用是已存在的变量的别名,它必须在定义时初始化,并且不能重新绑定到另一个变量。指针可以是空指针(nullptr),它不…...
spring boot 整合多数据源
多数据源产生的场景 一般情况下,不会有多数据源这样的场景出现,但老项目或者特殊需求的项目,可能会有这样的场景 同一个应用需要访问两个数据库不用数据库中间件的读写分离 注入数据源选择的时机 声明两个数据源实例,在getConnect…...
数据集成:数据挖掘的准备工作之一
⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…...
xml配置文件密码特殊字符处理
错误姿势: 正确姿势:采取转义符的方式 常用转义符:...
遥感数据与作物模型同化
基于过程的作物生长模拟模型DSSAT是现代农业系统研究的有力工具,可以定量描述作物生长发育和产量形成过程及其与气候因子、土壤环境、品种类型和技术措施之间的关系,为不同条件下作物生长发育及产量预测、栽培管理、环境评价以及未来气候变化评估等提供了…...
UI库DHTMLX Suite v8.2发布全新表单组件,让Web表单实现高度可定制!
DHTMLX Suite v8.2日前已正式发布,此版本的核心是DHTMLX Form,这个小部件接收了4个备受期待的新控件,如Fieldset、Avatar、Toggle和ToggleGroup。官方技术团队还为Grid和TreeGrid小部件中的页眉/页脚工具提示提供了一系列新的配置选项等。 在…...
河北省图书馆典藏《乡村振兴振兴战略下传统村落文化旅游设计》许少辉八一新著
河北省图书馆典藏《乡村振兴振兴战略下传统村落文化旅游设计》许少辉八一新著...
什么是卷积002
文章目录 前言1.卷积网络和传统网络区别2.卷积神经网络整体架构1.输入层2. 卷积层3.池化层4.全连接层 5.神经网络6.经典网络1.Alexnet2. Vgg3.Resnet 残差网络-特征提取 7.感受野 前言 大纲目录 首先链接图像颜色通道 1.卷积网络和传统网络区别 右边的就是CNN,卷…...
黑马JVM总结(八)
(1)StringTable面试题 1.8 1.6时 (2)StringTable的位置 jvm1.6时StringTable是常量池的一部分,它随着常量池存储在永久代当中,在1.7、1.8中从永久代变成了堆中,为什么做这个更改呢?…...
开源网安入选广东省网络空间安全标准化技术委员会新技术及应用安全技术工作组成员单位
近日,第二届广东省网络空间安全标准化技术委员会(GD/TC 124)(以下简称省网安标委)正式成立。为进一步发挥省网安标委在支撑网络强国建设、推进网络安全产业高质量发展过程中,示范引领核心技术攻关、创新产品…...
Nginx配置指南:如何定位、解读与优化Linux上的Nginx设置
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🐅🐾猫头虎建议程序员必备技术栈一览表📖: 🛠️ 全栈技术 Full Stack: 📚…...
辉瑞与吉利德科学:制药巨头的新冠病毒之战
来源:猛兽财经 作者:猛兽财经 总结: (1)猛兽财经认为,华尔街低估了辉瑞(PFE)和吉利德科学(GILD)的前景,因为它们在开发新冠病毒疫苗和药物方面都…...
x86架构基础汇编知识
通用寄存器 EAX 32位 函数返回值 AX 低16位 AH 高八位 AL 低八位 EBX 32位 ECX 32位 循环次数,this指针 EDX 32位 EBP 32位 栈底寄存器 ESP 32位 栈顶寄存器 ESI 源索引寄存器 EDI 目标索引寄存器 EIP 无法直接通过汇编操作 例子 mov al,0xff …...
ThreadLocal的原理
ThreadLocal是Java中的一个类,它提供了线程本地变量的功能。每个线程都可以独立地访问自己的ThreadLocal变量,并且不会受到其他线程的干扰。 public class ThreadLocal<T> { ThreadLocal的原理是通过使用一个ThreadLocalMap来存储每个线程的变量副…...
Chrome 108版(64-bit 108.0.5359.125)网盘下载
还在用Selenium的朋友们注意了,目前Chrome的最新版是116,而官方的Chromedriver只支持到115版。 可惜Google不提供旧版Chrome的下载方式,需要旧版的很难回去了。如果真的想要旧版的Chrome,只能民间自救。 我在2022年12月备份了C盘…...
Mars3d插件参考开发教程并在相关页面引入
问题场景: 1.在使用Mars3d热力图功能时,提示mars3d.layer.HeatLayer is not a constructor 问题原因: 1.mars3d的热力图插件mars3d-heatmap没有安装引用。 解决方案: 1.参考开发教程,找到相关的插件库:Mars3D 三维…...
Windows 性能突然打鸡血,靠 Bug 修复了多年顽疾
要说 的 Bug 集中地,当属资源管理器。 速度缓慢、卡顿、崩溃,不同设备、不同版本的用户都有不同的感受。 严格来说,这其实是 Windows 的传统艺能,要完美修复可不容易。 而作为小老弟的文件资源管理器,时不时来个无响…...
亚马逊封买家账号的原因有哪些
亚马逊可能封锁买家账号的原因有多种,主要是出于保护市场和维护平台秩序的考虑。以下是一些可能导致亚马逊封锁买家账号的常见原因: 1、涉及违规行为:如果买家违反了亚马逊的使用政策,如发表虚假评价、滥用退货政策、欺诈或盗窃等…...
1.0零基础尝试DCM通讯(c-store)
前言 本项目是对医院放疗及相关设备的互通互联。对dcm文件及数据协议是本项目的基础。 今天在项目组成员支持下,对dcm通讯进行了初步的尝试,有人之路,这个过程可以说是非常愉快,于是乎准备将这个愉快的过程记录,方便自己查阅和后来人。 c-store 本次的安装和测试使用的…...
vue之封装tab类组件
vue之封装tab类组件 vue之封装tab类组件CSS样式方面JS方面 vue之封装tab类组件 需求:点击【上一步】、【下一步】按钮,切换tab,且有淡入浅出的动画。 CSS样式方面 <div class"parent"><div class"childDiv" id…...
固定资产管理中净值怎么算
在资产管理的领域中,我们经常听到“净值”这个词。然而,对于许多人来说,净值的概念仍然模糊不清。本文将试图揭示固定资产管理的净值计算方法,并提供一些创新的观点。 我们需要明确什么是净值。在财务术语中,净值是…...
SQlite操作后如何正确退出
在 C 语言中,使用 SQLite 库进行数据库操作后,可以通过以下步骤来正常退出和关闭 SQLite 连接: 关闭数据库连接:在完成数据库操作后,使用 sqlite3_close() 函数来关闭 SQLite 连接。该函数接受一个指向 sqlite3 数据库…...
乐清网站设计制作/网站百度不收录
IOS7 webview全屏导致状态栏悬浮在页面上解决方案:打开 ios项目/classes/MainViewController.m,修改viewWillAppear方法- (void)viewWillAppear:(BOOL)animated{// View defaults to full size. If you want to customize the views size, or its subvie…...
开发网站做图文水印逻辑/厦门关键词优化报价
⑴目前世界上第一台光脑已由欧共体研制成功,这是一台全光数字计算机,其运算速度比电脑快一千倍。⑵光脑和电脑的工作原理基本一样,所不同的是光子代替了电子;光互连代替了电子导线互连;光开关、光三极管、光存储器、反…...
国外自助建站免费建站平台/百度分公司
首先要安装 Ruby Ruby安装教程http://www.runoob.com/ruby/ruby-installation-windows.html Ruby 官网 http://rubyinstaller.org/downloads/ 安装成功后 在ruby安装目录的bin目录下 的cmd中执行 命令: gem install jekyll 等待安装jekyll...
c 网站开发 pdf/吉林网站seo
FROM: http://www.cnblogs.com/CsOH/p/5904430.html 问题:有n个数组成一个序列,有m个形如询问L, R的询问,每次询问需要回答区间内至少出现2次的数有哪些。 朴素的解法需要读取O(nm)次数。如果数据范围小,可以用数组,时…...
网站如何做背景音乐/网址收录入口
系列文章目录 🍑 2022年Python大数据学习路线图,源码笔记,最优学习资源 🍑 2022年人工智能学习路线图,清楚明确 🍑 作为一个程序员,怎样才算精通 Python? 🍑 Python面…...
深圳软件公司排行/seo网站推广推荐
2019独角兽企业重金招聘Python工程师标准>>> 本文是MyEclipse方面教程,主要介绍在MyEclipse中该如何设置jsp页面为默认utf-8编码? 在MyEclispe中创建Jsp页面,Jsp页面的默认编码是“ISO-8859-1”,如下图所示:…...