Spring注解驱动开发--AOP底层原理
Spring注解驱动开发–AOP底层原理
21. AOP-AOP功能测试
AOP:【动态代理】
指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
1、导入aop模块:Spring AOP,(Spring-aspects)
2、定义一个业务逻辑类(MathCalculator):在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常、xxx)
3、定义一个日志切面类(LogAspects);切面类里面的方法需要动态感知MathCalculator,div运行到哪里然后哪里就执行。
通知方法:
前置通知(@Before):logStart:在目标方法(div)运行之前运行
后置通知(@After):logENd:在目标方法(div)运行结束之后运行
返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
环绕通知(@Around):动态代理:手动推进目标方法运行(joinPoint.procces())
4、给切面类的目标方法标注何时何地地运行(通知注释)
5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中
6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
【7】、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
在Spring中很多的 @EnableXXX;
三步:
1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
3)、开启基于注解的aop模式:@EnableAspectJAutoProxy
第一步、导入aop模块
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>4.3.12.RELEASE</version></dependency>
第二步、定义一个业务逻辑类(MathCalculator)
public class MathCalculator {public int div(int i,int j){System.out.println("MathCalculator...div...");return i/j;}}
第三步、定义一个日志切面类(LogAspects)
/*** 切面类** @Aspect:告诉Spring当前类是一个切面类*/
@Aspect //告诉Spring当前类是一个切面类
public class LogAspects {//抽取公共的切入点表达式//1.本类引用//2.其他的切面引用@Pointcut("execution(public int com.xjz.aop.MathCalculator.*(..))")public void pointCut(){};//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)@Before("pointCut()")public void logStart(JoinPoint joinPoint){Object[] args = joinPoint.getArgs();System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+ Arrays.asList(args) +"}");}@After("com.xjz.aop.LogAspects.pointCut()")public void logEnd(JoinPoint joinPoint){System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");}//JoinPoint一定要出现在参数表的第一位@AfterReturning(value = "pointCut()",returning = "result")public void logReturn(JoinPoint joinPoint,Object result){System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");}@AfterThrowing(value = "pointCut()",throwing = "exception")public void logException(JoinPoint joinPoint,Exception exception){System.out.println(""+joinPoint.getSignature().getName()+"异常。。。@AfterThrowing:异常信息:{"+exception+"}");}
}
第四步、将切面类和业务逻辑类(目标方法所在类)都加入到容器中
@EnableAspectJAutoProxy //开启基于注解的aop模式
@Configuration
public class MyConfigOfAOP {//业务逻辑类加入到容器中@Beanpublic MathCalculator calculator(){return new MathCalculator();}//切面类加入到容器中@Beanpublic LogAspects logAspects(){return new LogAspects();}}
第五步、测试
public class IOCTest_AOP {@Testpublic void test01(){AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfAOP.class);//1.不要自己创建对象
// MathCalculator mathCalculator = new MathCalculator();
// mathCalculator.div(1,1);MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);mathCalculator.div(1,1);applicationContext.close();}
}
第六步、运行结果
- 正常返回

- 异常报错

22. AOP原理
AOP:【动态代理】指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
1、导入aop模块:Spring AOP,(Spring-aspects)
2、定义一个业务逻辑类(MathCalculator):在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常、xxx)
3、定义一个日志切面类(LogAspects);切面类里面的方法需要动态感知MathCalculator,div运行到哪里然后哪里就执行。通知方法:前置通知(@Before):logStart:在目标方法(div)运行之前运行后置通知(@After):logENd:在目标方法(div)运行结束之后运行返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行环绕通知(@Around):动态代理:手动推进目标方法运行(joinPoint.procces())
4、给切面类的目标方法标注何时何地地运行(通知注释)
5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中
6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
【7】、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】在Spring中很多的 @EnableXXX;
三步:1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)3)、开启基于注解的aop模式:@EnableAspectJAutoProxy
AOP原理:【看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么?】@EnableAspectJAutoProxj;1、@EnableAspectJAutoProxj是什么?@Import(AspectJAutoProxyRegistrar.class):给容器中导入AspectJAutoProxyRegistrar利用AspectJAutoProxyRegistrar自定义给容器中注册bean;BeanDefinetioninternalAutoProxyCreator = AnnotationAwareAspectJAutoProxyCreator;给容器中注册一个AnnotationAwareAspectJAutoProxyCreator;2、AnnotationAwareAspectJAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator->AspectJAwareAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAutoProxyCreatorimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware关注后置处理器(在bean初始化完成前后做事情)、自动装配BeanFactoryAwareAbstractAutoProxyCreator.setBeanFactory()AbstractAutoProxyCreator.有后置处理器的逻辑;AbstractAdvisorAutoProxyCreator.setBeanFactory()-->initBeanFactory()AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()流程:1)、传入配置类,创建ioc容器2)、注册配置类,调用refresh()刷新容器;3)、registerBeanPostProcessors(beanFactory);注册bean的后置处理器来方便拦截bean的创建;1)、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor2)、给容器中加别的BeanPostProcessor3)、优先注册实现了呢PriorityOrdered接口的BeanPostProcessor;4)、再给容器中注册实现了Ordered接口和BeanPostProcessor;5)、注册没实现优先级接口的BeanPostProcessor6)、注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中;创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxy】1)、创建Bean的实例;2)、populateBean:给bean的各种属性赋值3)、initializeBean:初始化bean;1)、invokeAwareMethods():处理Aware接口的方法回调2)、applyBeanPostProcessorBeforeInitialization():应用后置处理器的postProcessBefore3)、invokeInitMethods():执行自定义的初始化方法4)、applyBeanPostProcessorAfterInitialization():执行后置处理器的postProcessAfterIn4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功:--》aspectJAdvis7)、把BeanPostProcessor注册到BeanFactory中:beanFactory.addBeanPostProcessor(postProcessor);
========以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程===========AnnotationAwareAspectJAutoProxyCreator =》 InstantiationAwareBeanPostProcessor4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;创建剩下的单实例Bean1)、遍历获取容器中所有的Bean,依次创建对象getBean(beanName);getBean->doGetBean()->getSingleton()->2)、创建bean【AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostP1)、先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;只要创建好的Bean都会被缓存起来2)、createBean();创建bean;AnnotationAwareAspectJAutoProxyCreator会在任何bean创建之前先尝试返回bean的实例【BeanPostProcessor是在Bean对象创建完成初始化前后调用的】【InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的】1)、resolveBeforeInstantiation(beanName,mbdToUse);解析BeforeInstantiation希望后置处理器在此前能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续1)、后置处理器先尝试返回对象:bean = applyBeanPostProcessorsBeforeInstantiation();拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor;就执行postProcessBeforeInstantiationif (bean != null) {bean = applyBeanPostProcessorsBeforeInstantiation(bean,beanName)}2)、doCreateBean(beanName, mbdToUse, args);真正的去创建一个bean实例;和3.6流程一样3)、AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】的使用:1)、每一个bean创建之前,调用postProcessBeforeInstantiation();关心MathCalculator和LogAspect的创建1)、判断当前bean是否在advisedBeans中(保存了所有需要增强bean)2)、判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AOPInfrastructureBean.或者是否是切面(@Aspect)3)、是否需要跳过1)、获取候选的增强器(切面里面的通知方法)【List<Advisor、candidateAdvisors】每一个封装的通知方法的增强器是InstantiationModelAwarePointcutAdvisor;判断每一个增强器是否是AspectJPointcutAdvisor类型的;返回true2)、永远返回false2)、创建对象postProcessAfterInitialization;return wrapIfNecessary(bean, beanName,cacheKey);//包装如果需要的情况下1)、获取当前bean的所有增强器(通知方法)1、找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)2、获取到能在bean使用的增强器。3、给增强器排序2)、保存当前bean在advisedBeans中:3)、如果当前bean需要增强,创建当前bean的代理对象;1)、获取所有增强器(通知方法)2)、保存到proxyFactory3)、创建代理对象;Spring自动决定JdkDynamicAopProxy(config);jdk动态代理ObjenesisCglibAopProxy(config);cglib的动态代理4)、给容器中返回当前组件使用cglib增强了的代理对象;5)、以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程3)、目标方法执行:容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);1)、CglibAopProxy.intercept();拦截目标方法的执行2)、根据ProxyFactory对象获取将要执行的目标方法拦截器链;List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvi1)、List<Object> interceptorList保存所有拦截器一个默认的ExposeInvocationinterceptor 和4个增强器;2)、遍历所有的增强器,将其转为Interceptorregistry.getInterceptors(advisor);3)、 将增强器转为List<MethodInterceptor>数组;如果是MethodInterceptor,直接加入到集合中如果不是,使用AdvisorAdapter将增强器转为MethodINterceptor;转换完成返回MethodInterceptor数据;3)、如果没有拦截器链,直接执行目标方法;拦截器链(每一个通知方法又被包装为方法拦截器)4)、如果有拦截器链,把需要执行的目标对象、目标方法,拦截器链等信息传入创建一个CglibMethodInvocation对象;并调用 Object retVal = mi.proceed();5)、拦截器链的触发过程1)、如果没有拦截器执行目标方法,或者拦截器的索引和拦截器数据-1大小一样(指定到了最后一个拦截器)执行目标方法;2)、链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;拦截器链的机制,保证通知方法与目标方法的执行顺序总结:1)、@EnableAspectJAutoProxy 开启AOP功能2)、@EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator3)、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;4)、容器的创建流程:1)、registerBeanPostProcessors() 注册后置处理器;创建 AnnotationAwareAspectJAutoProxyCreator对象2)、finishBeanFactoryInitialization()初始化剩下的单实例bean1)、创建业务逻辑组件和切面组件2)、AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程3)、组件创建完之后,判断组件是否需要增强是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);5)、执行目标方法:1)、代理对象执行目标方法2)、CglibAopProxy.intercept();1)、得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)2)、利用拦截器的链式机制,依次进入每一个拦截器进行执行;3)、效果:(Spring4):正常执行,前置通知-》目标方法-》后置通知-》返回通知出现异常,前置通知-》目标方法-》后置通知-》异常通知(Spring5):正常执行,前置通知-》目标方法-》返回通知-》后置通知出现异常,前置通知-》目标方法-》异常通知-》后置通知

**注意:**一定要跟着雷老师进源码,不然很快就会忘掉的!!
相关文章:
Spring注解驱动开发--AOP底层原理
Spring注解驱动开发–AOP底层原理 21. AOP-AOP功能测试 AOP:【动态代理】 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式; 1、导入aop模块:Spring AOP,(Spring-aspects) 2、定义一个业务逻辑类(Ma…...
对象的动态创建和销毁以及对象的复制,赋值
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才…...
JVM调优,调的是什么?目的是什么?
文章目录前言一、jvm是如何运行代码的?二、jvm的内存模型1 整体内存模型结构图2 堆中的年代区域划分3 对象在内存模型中是如何流转的?4 什么是FULL GC,STW? 为什么会发生FULL GC?5 要调优,首先要知道有哪些垃圾收集器及哪些算法6 调优不是盲目的,要有依据,几款内…...
docker部署zabbix监控
docker部署zabbix监控 1、环境说明 公有云ubuntu22.04 系统->部署docker环境zabbix-server 6.4 2、准备docker环境 更新apt以及安装一些必要的系统工具 sudo apt-get update sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-co…...
C语言刷题(6)(猜名次)——“C”
各位CSDN的uu们你们好呀,今天,小雅兰还是在复习噢,今天来给大家介绍一个有意思的题目 题目名称: 猜名次 题目内容: 5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果: A选…...
两年外包生涯,感觉自己废了一半....
先说一下自己的情况。大专生,17年通过校招进入湖南某软件公司,干了接近2年的点点点,今年年上旬,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了五年的功能测试…...
【python】喜欢XJJ?这不得来一波大采集?
前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 俗话说的好:技能学了~就要用在自己喜欢得东西上!! 这我不得听个话~我喜欢小姐姐,跳舞的小姐姐 这不得用python把小姐姐舞采集下来~嘿嘿嘿 完整源码、素材皆可点击文章下方名片…...
公司测试员用例写得乱七八糟,测试总监制定了这份《测试用例编写规范》
统一测试用例编写的规范,为测试设计人员提供测试用例编写的指导,提高编写的测试用例的可读性,可执行性、合理性。为测试执行人员更好执行测试,提高测试效率,最终提高公司整个产品的质量。 一、范围 适用于集成测试用…...
LeetCode 热题 HOT 100【题型归类汇总,助力刷题】
介绍 对于算法题,按题型类别刷题才会更有成效,因此我这里在网上搜索并参考了下 “🔥 LeetCode 热题 HOT 100” 的题型归类,并在其基础上做了一定的完善,希望能够记录自己的刷题历程,有所收获!具…...
【Java进阶篇】—— File类与IO流
一、File类的使用 1.1 概述 File 类以及本章中的各种流都定义在 java.io 包下 一个File对象代表硬盘或网络中可能存在的一个文件或文件夹(文件目录) File 能新建、删除、重命名 文件和目录,但 File不能访问文件内容本身。如果我们想要访问…...
Mysql 竟然还有这么多不为人知的查询优化技巧,还不看看?
前言 Mysql 我随手造200W条数据,给你们讲讲分页优化 MySql 索引失效、回表解析 今天再聊聊一些我想分享的查询优化相关点。 正文 准备模拟数据。 首先是一张 test_orde 表: CREATE TABLE test_order (id INT(11) NOT NULL AUTO_INCREMENT,p_sn VARCHA…...
MATLAB算法实战应用案例精讲-【智能优化算法】海洋捕食者算法(MPA) (附MATLAB和python代码实现)
目录 前言 知识储备 Lvy 飞行 布朗运动 算法原理 算法思想 数学模型...
Spring @Profile
1. Overview In this tutorial, we’ll focus on introducing Profiles in Spring. Profiles are a core feature of the framework — allowing us to map our beans to different profiles — for example, dev, test, and prod. We can then activate different profiles…...
Vue3电商项目实战-个人中心模块4【09-订单管理-列表渲染、10-订单管理-条件查询】
文章目录09-订单管理-列表渲染10-订单管理-条件查询09-订单管理-列表渲染 目的:完成订单列表默认渲染。 大致步骤: 定义API接口函数抽取单条订单组件获取数据进行渲染 落的代码: 1.获取订单列表API借口 /*** 查询订单列表* param {Number…...
【十二天学java】day01-Java基础语法
day01 - Java基础语法 1. 人机交互 1.1 什么是cmd? 就是在windows操作系统中,利用命令行的方式去操作计算机。 我们可以利用cmd命令去操作计算机,比如:打开文件,打开文件夹,创建文件夹等。 1.2 如何打…...
【面试题】闭包是什么?this 到底指向谁?
一通百通,其实函数执行上下文、作用域链、闭包、this、箭头函数是相互关联的,他们的特性并不是孤立的,而是相通的。因为内部函数可以访问外层函数的变量,所以才有了闭包的现象。箭头函数内没有 this 和 arguments,所以…...
汽车4S店业务管理软件
一、产品简介 它主要提供给汽车4S商店,用于管理各种业务,如汽车销售、售后服务、配件、精品和保险。整个系统以客户为中心,以财务为基础,覆盖4S商店的每一个业务环节,不仅可以提高服务效率和客户满意度,…...
基于 pytorch 的手写 transformer + tokenizer
先放出 transformer 的整体结构图,以便复习,接下来就一个模块一个模块的实现它。 1. Embedding Embedding 部分主要由两部分组成,即 Input Embedding 和 Positional Encoding,位置编码记录了每一个词出现的位置。通过加入位置编码可以提高模型的准确率,因为同一个词出现在…...
算法小抄6-二分查找
二分查找,又名折半查找,其搜索过程如下: 从数组中间的元素开始,如果元素刚好是要查找的元素,则搜索过程结束如果搜索元素大于或小于中间元素,则排除掉不符合条件的那一半元素,在剩下的数组中进行查找由于每次需要排除掉一半不符合要求的元素,这需要数组是已经排好序的或者是有…...
大学四年..就混了毕业证的我,出社会深感无力..辞去工作,从头开始
时间如白驹过隙,一恍就到了2023年,今天最于我来说是一个值得纪念的日子,因为我收获了今年的第一个offer背景18年毕业,二本。大学四年,也就将就混了毕业证和学位证。毕业后,并未想过留在湖南,就回…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
