SpringAOP 原理解析
什么是AOP?
1: 传统的OOP编程他的代码逻辑是一种自上向下, 而在这些自上而下的过程中会产生一些横切性的问题,比如说:日志信息,权限校验认证,事务等,
2: 这些横切性问题,往往与我们的主业务逻辑关系不大,并且散落在代码的各个地方,维护麻烦, AOP就是解决这个问题的,将主业务逻辑和这些横切性问题分离,达到解耦
如图所示:

SpringAop底层原理: 1:JDK代理, 2: cglib动态代理
对目标对象的方法进行前置处理,后置处理,这些处理的代码加到目标代码前后的过程叫: 织入, 那么 JDK代理和 cglib代理分别是什么时候织入呢? 编译期还是运行期? 如果是运行期,那么是在运行期spring容器初始化的时候织入?还是我们拿到这个目标对象的时候织入的(织入后将对象放入容器中)?
让我们一点一点深入了解
先说答案: 织入,实在运行期Spring容器初始化的时候织入的.它也属于Bean的生命周期一部分, 将生成的代理对象放入单例池中, spring容器初始化的时候, 会扫描xml,或者有@Component注解的类,根据这些类和他的注解(比如scope,islaze...)生成BeanDefinition,全部扫描完成的时候,BeanFactory就组建完成了,然后BeanFactoryPostProcessor,后置处理,在这个处理过程中,bean的属性注入,同时aop也生成了代理对象(放置了拦截器调用链),
使用AspectJ,步骤:
1: 添加依赖(aspectjweaver)
2: 配置类上添加注解:@EnableAspectJAutoProxy
3: 定义一个切面类(类上如果有这个注解@Aspect ,那么他就是一个切面类),并交给spring容器管理,@Component
4: 声明一个切点, 切面类中的某个方法上如果有这个注解(@PointCut("excution(* com.boo.service..(..))")), 关于切点表达式可以自己看官方文档
5: 定义通知: 如果一个方法上有注解@AfterReturning("com.aop.config.UserAspectJ.pointCut()"), 说明这个是后置通知, 括号中是指向当前切面类的切点
6: 启动容器,测试
那么在spring源码中是如何实现AOP的? 几个关键的类
https://www.cnblogs.com/51life/p/9243021.html , 这里引用别人的笔记..感谢他
1: 查看源码中Bean初始化过程中,是如何解析xml 中的aop:aspectj-autoproxy/,
AbstractApplicationContext类: 的refresh()方法中的obtainFreshBeanFactory(); 作用:初始化容器, 解析xml中的标签(包括 pointCut标签,ADVISOR标签,ASPECT标签...)将Bean转换为BeanDefiniton
2: refresh()方法中的registerBeanPostProcessors(beanFactory); 作用: 注册各种各样的Bean后置处理器,这里就包括了AspectJAwareAdvisorAutoProxyCreator(这个是aop后置处理器)
3: AbstractAutowireCapableBeanFactory类的initializeBean()方法: 作用是实例化Bean,并给Bean注入属性(这个方法中可以看到 各种 ...Aware...类的回调自身赋值属性 ), 这里就包括了目标对象的实例化和注入属性,目标对象生成之后,最后一步是AspectJAwareAdvisorAutoProxyCreator(这个是aop后置处理器)开始处理目标对象,AbstractAutoProxyCreator类中的 createProxy()方法,进而生成代理对象, 这里会看到有二种代理方式: JDK代理 cglib代理, 将生成的代理对象放入单例池
4: 代理对象生成之后,那么"织入"这个是如何实现呢? 拦截器实现. AbstractAutoProxyCreator类中的 createProxy()方法中不仅仅生成了代理对象, 生成代理对象的时候同时也将 拦截器调用链放置到代理对象中了, Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 这个this,就是调用自身的invoke()方法, 这个方法中可以看到 retVal = invocation.proceed();这个是AOP的核心,如何对目标进行增强的
1: AbstractApplicationContext类: 的refresh()----obtainFreshBeanFactory();---loadBeanDefinitions(beanFactory);---XmlWebApplicationCotnext类的loadBeanDefinitions()--loadBeanDefinitions(beanDefinitionReader);----reader.loadBeanDefinitions(configLocation);-----int count = loadBeanDefinitions(resources);----XmlBeanDefinitionReader类的loadBeanDefinitions----doLoadBeanDefinitions(inputSource, encodedResource.getResource());---documentReader.registerBeanDefinitions(doc, createReaderContext(resource));---parseBeanDefinitions(root, this.delegate);-----delegate.parseCustomElement(ele);(这个是解析其他的标签,而非默认的(beans,alias..))----handler.parse---ConfigBeanDefinitionParser类的parseAspect, 这里就可以看到解析POINTCUT 标签,ASPECT标签, 转换为BeanDefinition然后存入list中
2: refresh()----registerBeanPostProcessors(beanFactory); 这个方法的逻辑是,先获取所有的后置处理器,然后分类存储, 然后创建对应的处理器,这里就包括了AspectJAwareAdvisorAutoProxyCreator
3: AbstractAutowireCapableBeanFactory类的initializeBean()----applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);-----AbstractAutoProxyCreator类wrapIfNecessary(bean, beanName, cacheKey);---createProxy---proxyFactory.getProxy(getProxyClassLoader());----这里会看到二个实现类 CglibAopProxy JdkDynamicAopProxy
4: 织入的实现: AbstractAutoProxyCreator类中createProxy()----invoke()--List
SpringAOP 原理解析的更多相关文章
- [原][Docker]特性与原理解析
Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...
- 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...
- Web APi之过滤器执行过程原理解析【二】(十一)
前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...
- Web APi之过滤器创建过程原理解析【一】(十)
前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...
- GeoHash原理解析
GeoHash 核心原理解析 引子 一提到索引,大家脑子里马上浮现出B树索引,因为大量的数据库(如MySQL.oracle.PostgreSQL等)都在使用B树.B树索引本质上是对索引字段 ...
- alibaba-dexposed 原理解析
alibaba-dexposed 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49821413 原理参考地址: htt ...
- 支付宝Andfix 原理解析
支付宝Andfix 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49802429 原理参考地址: http://blo ...
- JavaScript 模板引擎实现原理解析
1.入门实例 首先我们来看一个简单模板: <script type="template" id="template"> <h2> < ...
- Request 接收参数乱码原理解析三:实例分析
通过前面两篇<Request 接收参数乱码原理解析一:服务器端解码原理>和<Request 接收参数乱码原理解析二:浏览器端编码原理>,了解了服务器和浏览器编码解码的原理,接下 ...
随机推荐
- 逆向 string.h 函数库 strlen、memchr、strcat 函数
strlen 函数 主要功能:返回字符串的长度 C/C++ 实现: #include <iostream> #include <stdio.h> #include <st ...
- RDPInception攻击手法
在讲RDPInception攻击手段之前,我们先了解一下RDP远程桌面(Remote Desktop Protocol)协议.RDP远程桌面协议(Remote Desktop Protocol)是一个 ...
- React-状态提升
通常,多个组件需要反映相同的变化数据,这时建议将共享状态提升到最近的共同父组件中去. <!DOCTYPE html> <html> <head> <meta ...
- 解决GET http://localhost:8080/js/layui/layui.js net::ERR_ABORTED 404
用ssm+layui在写页面的时候,发现无法找到资源路径 <script src="js/layui/layui.js" charset="utf-8"& ...
- springmvcdemo
项目点击属性 2.3 转换成2.5 已经变成一个网站项目了 报错消失 pom.xml <project xmlns="http://maven.apache.or ...
- Mybatis学习之自定义持久层框架(四) 自定义持久层框架:生产sqlSession
前言 上一回我们完成了数据库配置文件的读取和解析工作,有了这些准备工作,我们就可以与数据库创建连接和会话了,所谓sqlSession就是数据库的会话,一切增删查改操作都是在与数据库的会话中完成,下面我 ...
- Vulkan移植GPUImage(五)从P到Z的滤镜
现aoce_vulkan_extra把GPUImage里从P到Z的大部分滤镜用vulkan的ComputeShader实现了,也就是最后一部分的移植,整个过程相对前面来说比较简单,大部分我都是直接复制 ...
- python工业互联网应用实战15-前后端分离模式1
我们在13章节里通过监控界面讲了如何使用jquery的动态加载数据写法,通过简单案例来说明了如何实现动态的刷新监控界面的数据,本章我们将演示如何从Django模板加载数据逐步演化到前后端分离的异步数据 ...
- 【敏杰开发】Scrum Meeting 博客汇总
敏杰开发团队 Scrum Meeting 博客汇总 项目名称:[知识路书] 一.Alpha阶段 Scrum meeting 1 2020/04/07 选题 Scrum meeting 2 2020/0 ...
- [bug] kafka启动报错 could not be established. Broker may not be available.
原因 配置文件和命令行中的主机名不一致,建议都用ip地址 参考 https://blog.csdn.net/getyouwant/article/details/79000524