Spring源码学习(二)AOP
----ProxyFactoryBean这个类,这是AOP使用的入口----
AOP有些特有的概念,如:advisor、advice和pointcut等等,使用或配置起来有点绕,让人感觉有些距离感,其实它的实现就是一组标准的设计模式的组合使用:Factory、Proxy、Chain of Responsibility,只要搞清楚这几个设计模式,读AOP的源码是比较容易的。
首先看看ProxyFactoryBean这个类,这是AOP使用的入口,从AOP拿到的bean object就是ProxyFactoryBean.getObject得到的,从这条线下去,发现AOP就是通过Proxy模式从实际要执行的target做了包装,而Proxy还不止一套方案,通过Factory封装了两套Proxy实现方案:JDK 动态Proxy和Cglib Proxy。有两套实现主要是因为JDK 动态Proxy必须要target实现某个接口,如果不满足这个条件就会用Cglib增强字节码的方式来实现proxy。
就拿JDK Proxy为例,Spring AOP使用了标准的JDK提供的动态Proxy方案,我们先看看标准的动态Proxy是什么样子,看下面类图:

Cilent通过Proxy.newProxyInstance(classLoader, proxiedInterfaces, invocationHandler);就能拿到target的proxy object,在执行target的方法时就会先执行到DynamicProxy中的invoke方法从而实现代理包装。基于这个道理来看Spring AOP的实现,实际上就是标准地基于这个方式来做的,Spring AOP的所有花招都体现在JdkDynamicAopProxy.invoke中(当然在Cglib中是通过callback来做的,道理类似)。
通过看JdkDynamicAopProxy.invoke的源码会发现,Spring AOP的各种花招是通过Chain of Responsibility模式串起来的,先看看一个标准的Chain of Responsibility是什么样子,看下面的类图:

而Chain of Responsibility的关键在于Invocation与Interceptor的配合,主要原则就两条:
1)Invocation需要维护Interceptor集合和游标,每次调用invoke时需要先调用游标所在的Interceptor.invoke,如果游标已超过最后一个Interceptor,则调用实际target的方法
2)Interceptor的invoke中除了要执行自己的拦截逻辑,还要通过Invocation.invoke把调用传递下去,拦截的灵活性就体现在Invocation.invoke执行与否和执行的顺序。
以上逻辑通过时序图来看,如下图所示:

理解Chain of Responsibility后再来看Spring AOP,JdkDynamicAopProxy.invoke做的事情就是以上Client做的事情,
1)首先通过this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);组装interceptor chain
2)然后new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);得到invocation
3)最后通过invocation.proceed();启动责任链
而Spring AOP的那些概念都体现在组装interceptor chain中,advisor、advice和pointcut无非就是帮助你描述如何对Target进行拦截,对这一块感兴趣的朋友可以好好读读里面的代码。另外,Spring AOP提供了各种各样的Interceptor,来实现各种形式的横切,具体做法可以详细看看各Interceptor的实现。
综上所述,整个流程如下图所示:

总之,把握了Factory、Proxy、Chain of Responsibility的运用也就把握了Spring AOP的实现原理,道理虽然简单,但其中的精髓和原由还是值得我们继续深思的。
Spring源码学习(二)AOP的更多相关文章
- spring源码学习之AOP(二)
接着上一篇中的内容! 3.创建代理 在获取了所有的bean对应的增强器之后,便可以进行代理的创建了org.springframework.aop.framework.autoproxy包下的Abstr ...
- spring源码学习之AOP(一)
继续源码学习,看了spring中基础的容器和AOP感觉自己也没有什么长进,哈哈,我也不知道到底有用没有,这可能是培养自己的一种精神吧,不管那么多,继续学习!AOP中 AOP中几个重要的概念:(1)Ad ...
- spring源码分析(二)Aop
创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...
- [spring源码学习]二、IOC源码——配置文件读取
一.环境准备 对于学习源码来讲,拿到一大堆的代码,脑袋里肯定是嗡嗡的,所以从代码实例进行跟踪调试未尝不是一种好的办法,此处,我们准备了一个小例子: package com.zjl; public cl ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- spring源码学习之路---深入AOP(终)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...
- spring源码学习之路---IOC初探(二)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章当中我没有提及具体的搭 ...
- Spring 源码学习——Aop
Spring 源码学习--Aop 什么是 AOP 以下是百度百科的解释:AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程通过预编译的方式和运行期动态代理实 ...
- Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作
写在前面 上文 Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件主要讲Spring容器创建时通过XmlBeanDefinitionReader读 ...
- Spring源码学习
Spring源码学习--ClassPathXmlApplicationContext(一) spring源码学习--FileSystemXmlApplicationContext(二) spring源 ...
随机推荐
- Docker-2 的创建、启动、终止、删除、迁移等
学习博客地址:http://www.dwhd.org/20151115_140935.html
- .net架构设计读书笔记--第三章 第8节 域模型简介(Introducing Domain Model)
一.数据--行为转变 很长的时间,典型的分析方法或多或少是以下两种,第一,收集需求并做一些分析,找出有关实体 (例如,客户. 订单. 产品) 和进程来实现. 第二,手持这种理解你尝试推断一个物 ...
- Java常见异常
1. runtimeException子类: 1. java.lang.ArrayIndexOutOfBoundsException 数组索引越界异常.当对数组的索引值为负数或大于等于数组大小时 ...
- 遍历HashMap的四种方法
public static void main(String[] args) { Map<String,String> map=new HashMap<String,String&g ...
- BZOJ-1879 Bill的挑战 状态压缩DP
MD....怎么又是状压....... 1879: [Sdoi2009]Bill的挑战 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 537 Solved ...
- Codevs1299 切水果
题目描述 Description 简单的说,一共N个水果排成一排,切M次,每次切[L,R]区间的所有水果(可能有的水果被重复切),每切完一次输出剩下水果数量 数据已重新装配,不会出现OLE错误 时限和 ...
- Java线程之间通信
用多线程的目的:更好的利用CPU的资源.因为所有的多线程代码都可以用单线程来实现. 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程. 并行:多个CPU实例或者多台机器同时执行一段处理逻辑, ...
- C++ Standard-Library Random Numbers
Extracted from Section 17.4 Random Numbers, C++ Primer 5th. Ed. The random-number library generates ...
- Java中各种(类、方法、属性)访问修饰符与修饰符的说明
类: 访问修饰符 修饰符 class 类名称 extends 父类名称 implement 接口名称 (访问修饰符与修饰符的位置可以互换) 访问修饰符 名称 说明 备注 public 可以被本项目的所 ...
- Jsonp简单认识(后端使用的是asp.net mvc)
一.Jsonp简介:由于浏览器基于安全有同源策略(同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性)机制,所以前端无法使用Ajax来获取来获取其他域名下返回的数据,而Jsonp可 ...