AOP学习笔记二
Spring AOP采用Java作为AOP的实现语言(AOL),学习曲线平滑,Spring AOP对AspectJ也提供了很好的集成与支持。最为第二代的AOP,采用动态代理机制和字节码生产技术实现,在运行期间为目标对象生成一个代理对象,将横切逻辑织入到这个代理对象中,系统使用织入了横切逻辑的代理对象。
在深入剖析Spring AOP之前,我们有必要先了解一下代理模式,代理模式可以简单地分成:静态代理模式和动态代理模式。静态代理模式作为设计模式中比较简单的一种模式,我们不做过多的分析;动态代理模式是JDK1.3之后引入的,使用该机制,我们可以为指定的接口在系统运行期间动态地生成代理对象。动态代理机制与静态代理的区别就在于把原先的一个代理类划分成一个Proxy类再加一个InvocationHandler接口,Proxy负责生产相应的动态代理实例,InvocationHandler负责拦截相应的方法调用。InvocationHandler就是实现横切逻辑的地方,作用类似于Adcice。动态代理模式的缺陷是只对实现了Interface的类有效。Spring AOP默认使用动态代理机制,无效时采用名为CGLIB的动态字节码生产类库,为目标对象生成动态的代理对象实例。
我们知道,基于面向对象语言的继承性,子类对象可以作为父类来使用。但是,使用继承的方式具有和静态代理一样的问题,需要为每个不同类型的目标对象都单独创建相应的扩展子类,借助CGLIB这样的动态字节库,在系统运行期间动态地为目标生成相应的扩展子类。使用CGLIB的唯一限制是无法对final类和final方法进行复写。
Spring AOP只支持方法执行类型的Joinpoint,这样做是为了付出20%的努力达到80%的效果。Spring AOP中以接口定义Pointcut作为其AOP框架中所有Pointcut的最顶层抽象,其中定义了两个方法用来帮助扑捉相应的Jointpoint。
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
对于其中的ClassFilter和MethodMatcher,我们看一下他们的具体接口定义:
public interface ClassFilter {
boolean matches(Class clazz);
ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
public interface MethodMatcher {
boolean matches(Method method, Class targetClass);
boolean isRuntime();
boolean matches(Method method, Class targetClass, Object[] args);
MethodMather TRUE = TrueMethodMatcher.INSTANCE;
}
简单来说,ClassFilter的存在是为了进行类的过滤,粒度比较粗,MethodMatcher是做方法的过滤,而且为了提高性能重载了matches方法,分为静态过滤和动态过滤,它们之间的分界线是isRuntime方法。
在Spring AOP中,已经为我们提供了好几个Pointcut实现,满足我们一般的需求。我们来简单分析一下各种实现的特点。
+ NameMatchMethodPointcut 属于静态匹配的子类,只考虑方法名,不考虑参数
+ AbstractRegexMethodPointcut 利用正则表达式进行匹配,可以匹配整个方法签名
+ AnnotationMatchingPointcut 利用注解来进行匹配,分为类级别和方法级别
+ ComposablePointcut 可进行逻辑运行的Pointcut实现
+ ControlFlowPointcut 匹配程序的调用流程
除了以上介绍的各种Pointcut,如果有自己的需求,我们也可以实现自己的Pointcut。
Spring AOP加入了开源组织,Spring中Advice的实现全部遵循AOP Alliance规定的接口。我们知道Advice是承载横切逻辑的地方,根据自身实例能否被目标对象类的所有实例所共享,划分成per-class类型与per-instance类型。只有Introduction类型的Advice属于per-instance类型,不能共享。
下面,我们开始简单地介绍各种Advice:
+ Before Advice 可通过抛出异常来打断方法流程
+ ThrowsAdvice 可用来进行异常情况的监控
+ AfterReturningAdvice 可访问当前Joinpoint的返回值、方法、方法参数和目标对象,但是不能更改返回值。
+ Around Advice 就是MethodInterceptor接口,功能非常强大。
以上介绍的都是pre-class类型的Advice。下面我们开始介绍Introduction,该Advice可以在不改动目标类定义的情况下,为目标类添加新的属性以及行为。根据是否可以在运行时动态配置和判断当前Introduction可应用的目标接口类型,划分为静态分支和动态分支。
在知道Pointcut和Advice之后,我们再看把他们集合到一起的Aspect。AOP中Aspect可以包含多个Pointcut和多个Advice,而我们Spring AOP中的对等实体Advisor是一种特殊的Aspect,通常只持有一个Pointcut和一个Advice。关于Advisor的体系结构,我们可以简单地分成两个分支:
针对其中PointcutAdvisor,我们来看一下其常见的子类:
+ DefaultPointcutAdvisor 除了Intorduction以外的Advice都可以
+ NamematchMethodPointcutAdvisor 限制只能使用NameMatchMethodPointcut
+ RegexMethodPointcutAdvisor 限制只能使用AbstractRegexMethodPointcut
+ DefalutBeanfactoryPointcutAdvisor 绑定到了BeanFactory,使用较少
对于IntroductionAdvisor,其只能用于类级别的拦截,只能够使用Introduction型的Advice,其常见子类只有一个:
+ DefaultIntroductionAdvisor
为了解决同一个Joinpoint应用的多个Advice执行的先后顺序问题,我们可以指定它们的Order值,默认情况下,先声明的Adice优先级更高,更好的解决方案是直接在Advisor上指定它们的order值,值越小,优先级越高。
在Pointcut、Advice、Aspect等各种元素都已准备好的情况下,我们还需要准备的就是织入器了。AspectJ采用ajc编辑器作为它的织入器,JBoss AOP使用自定义的ClassLoader作织入器,Spring AOP使用类ProxyFactory作为织入器。注意,ProxyFactory并不是Spring中的唯一织入器,而是最常见织入器。使用织入器,我们只需要为其提供两样最基本的东西。
+ 将要织入的目标对象
+ 要应用的Aspect,也就是Advisor。
我们知道Spring内部使用了动态代理和CGLIB两种机制,所以ProxyFactory内部会根据一定的算法自动在这两个机制之间切换。注意:对于Advice和Advisor,Introduction的部分是不能与其他Advice和Advisor混用的。 我们知道,Spring中关于AOP的实现是通过ProxyFactory类来实现的。现在我们来看看ProxyFactory的具体细节,首先看它的根部AopProxy接口。
public interface AopProxy {
Object getProxy();
Object getProxy(ClassLoader classLoader);
}
Spring AOP框架使用AopProxy对不同代理实现机制进行抽象。其中AopProxy的相关结构图如下所示:
可以看到,不同的AopProxy实现的实例化过程采用了抽象工厂模式。
随着JDK和Spring的升级,现在Spring AOP的使用方式已经包含有三种形式了,他们分别是基于接口和XSD的第一代AOP、基于注解的第二代AOP、基于Schema的第二代AOP,虽然配置方式多了,但他们的效果是相同的,可以根据自己的实际情况进行选择。
下面我们来讲讲AOP的应用场景和案例:
+ 异常处理 主要针对unchecked exception
+ 安全检查 Spring security
+ 缓存
AOP虽然很好地解决了等多系统需求的问题,下面我们就来看看在使用AOP的过程中应该注意的一些问题。
+ 公开当前调用的代理对象的探讨
AOP学习笔记二的更多相关文章
- WPF的Binding学习笔记(二)
原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...
- AJax 学习笔记二(onreadystatechange的作用)
AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...
- [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计
源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...
- JMX学习笔记(二)-Notification
Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...
- java之jvm学习笔记二(类装载器的体系结构)
java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...
- Java IO学习笔记二
Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...
- 《SQL必知必会》学习笔记二)
<SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语 ...
- NumPy学习笔记 二
NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(二) indigo tools
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
随机推荐
- 前端数据统计用做Bootstrap的一些柱状图、饼状图和折线图案例
Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷. Bootstrap ...
- redis 扩展下载
自己保存一下 免得以后忘记还得重新找T-T http://windows.php.net/downloads/pecl/snaps/redis/2.2.5/ phpinfo查看自己的php信息下载对 ...
- SpringBoot + SwaggerUI
后台写接口,由于要提供接口文档给前台使用,所有研究了一下swagger,看到网上有篇文章写得不错,就直接拿过来了. swagger用于定义API文档. 好处: 前后端分离开发 API文档非常明确 测试 ...
- web微信开发前期准备最新详细流程
一.申请配置测试公众号与配置本地服务器 1.打开浏览器,输入:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login,微信扫码确 ...
- Jmeter+Badboy实战经验三 Jmeter关联相关知识
1. 什么时候需要使用关联? 有些参数是动态变化的,获取之后,再次操作的时候,参数的值已经发生了变化,这种情况下就会出现脚本不可运行的问题,就需要用到了关联 2. 关联是什么概念? 3.jmeter ...
- Vue 2.0初学后个人总结及分享
摘要:最近在上海找工作,发现Vue前景还不错,于是就打算先学习一下(之前了解过,但是一直没提到日程上)这篇随笔当是为了自己学习之后,做一个小的阶段性总结.希望本文的内容对于刚开始接触vue的朋友们有点 ...
- [LeetCode]House Robber II (二次dp)
213. House Robber II Total Accepted: 24216 Total Submissions: 80632 Difficulty: Medium Note: Thi ...
- bat文件的一些小技巧
bat文件的简介: bat文件是dos下的批处理文件.批处理文件是无格式的文本文件,它包含一条或多条命令.它的文件扩展名为 .bat 或 .cmd.在命令提示下键入批处理文件的名称,或者双击该批处理文 ...
- ASP提取字段中的图片地址
Function RegImg(TheStr) Dim RegEx Set RegEx = New RegExp '建立正则表达对象. RegEx.IgnoreCase =T ...
- Struts2学习笔记②
之前在跟着老师们做项目的时候经常会烦恼Struts.xml怎么配置,老师也没讲太清楚,都是说很简单,但是不懂的人就是太难了!哈哈,万事还是要靠自己的! struts.xml今天又看了几个小时的书,也跟 ...