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 ...
随机推荐
- 如何用PHP做到页面注册审核
用户注册后就有该条用户记录,你对用户表设一个"审核状态"字段,默认值设为"未审核",然后你写几句审核代码做成一个功能,按照你们的意愿若审核通过你把审核状态改为& ...
- chrome浏览器美化插件:让你的浏览器页面冒水泡, 游小鱼儿
下载插件和效果图 这是一个让你的浏览器冒泡泡的插件, 浏览网页的时候仿佛置身于海底世界: 插件下载地址:http://files.cnblogs.com/files/diligenceday/chro ...
- ASP.NET Core MVC上传、导入、导出知多少
前言 本君已成夜猫子,本节我们来讲讲ASP.NET Core MVC中的上传,这两天才研究批量导入功能,本节顺便简单搞搞导入.导出,等博主弄妥当了再来和大家一并分享. .NET Core MVC上传 ...
- Struts2之环境配置
在学习struts2之前,首先我们要明白使用struts2的目的是什么?它能给我们带来什么样的好处? 设计目标 Struts设计的第一目标就是使MVC模式应用于web程序设计.在这儿MVC模式的好处就 ...
- Linux i2c子系统(四) _从i2c-s3c24xx.c看i2c控制器驱动的编写
"./drivers/i2c/busses/i2c-s3c2410.c"是3.14.0内核中三星SoC的i2c控制器驱动程序, 本文试图通过对这个程序的分析, 剥离繁复的细节, 总 ...
- jquery与js的区别与基础操作
一.什么是 jQuery jQuery是一个JavaScript库,它通过封装原生的JavaScript函数得到一整套定义好的方法.它的作者是John Resig,于2006年创建的一个开源项目,随着 ...
- 微信小程序怎样提高应用速度小技巧
作者:vicyao, 腾讯web前端开发 高级工程师商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/294.htm ...
- java算法 蓝桥杯(题+答案) 压缩变换
10.压缩变换 (程序设计) 小明最近在研究压缩算法.他知道,压缩的时候如果能够使得数值很小,就能通过熵编码得到较高的压缩比.然而,要使数值很小是一个挑战. 最近,小明需要压缩一些正整数的序列,这些 ...
- ViewPager详解
一.ViewPager简介 ViewPager 如其名所述,是负责翻页的一个 View.准确说是一个 ViewGrop,包含多个 View 页,在手指横向滑动屏幕时,其负责对 View 进行切换.为了 ...
- IOS本地日志记录方案
我们在项目中日志记录这块也算是比较重要的,有时候用户程序出什么问题,光靠服务器的日志还不能准确的找到问题. 现在一般记录日志有几种方式: 1.使用第三方工具来记录日志,如腾讯的Bugly,它是只把程序 ...