AOP:面向切面编程,是一种设计理念,并非Spring特有。AOP通过横向分离关注点,把一些公共的辅助性组件代码从核心组件代码中剥离,降低组件之后的耦合性,提高组件代码的复用性。AOP有一些基本概念,网上到处都是,这里也不能免俗:
- 方面(Aspect): 一个关注点的模块化,这个关注点实现可能 另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。
- 连接点(Joinpoint):程序执行过程中明确的点,如方法的调 用或特定的异常被抛出。
- 通知(Advice):在特定的连接点,AOP框架执行的动作。各种类 型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架 包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器 链。
- 切入点(Pointcut): 指定一个通知将被引发的一系列连接点 的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。
- 引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。
- 目标对象(Target Object): 包含连接点的对象。也被称作 被通知或被代理对象。
AOP一般是代理技术和字节码替换技术的应用,通过在合适的时机替换掉原有的字节码来达到增加或替换原有的代码逻辑,这里的合适时机主要下面几个:
编译期:在类编译器就把切面织入,这种方式叫做静态织入,代表技术有AspectJ。因为切面是在编译期织入的,所以几乎不占运行时开销,性能比较好,但是需要特定的编译坏境,而且还要多学一门语法,学期曲线相对较陡。非常遗憾,一直没有对AspectJ语法做过深入的研究,所以后面的篇章不会过多的提到这种方式,后面的篇章会着重分析后面两种方式。
类加载期:在类加载时注入界面,Spring中LTW就是这种方式,Spring LTW也运用了AspectJ技术。由于是在类加载器织入,所以会占用一定的运行时开销,但是一般情况下,系统运行时大部分类只会被加载一次,所以对性能的影响也相对较小,这种方式一般是通过JVM代理(注意不是JDK动态代理)来实现的,所以运行时需要挂载一个JVM agent代理,这种方式还有一个潜在的好处,很容器实现插拔式的织入,比如我想在调试程序的时候织入切面但是运行时不织入,那只需要正式运行时不挂载代理就行了。
运行时:在运行注入,通过字节码增强技术比如JDK动态代理、CGLIB代理实现。切面织入在每次bean实例创建时执行,这种方式性能较差,但是使用最方便,不用特定的编译坏境,不用多学一门语言,也不用在运行时挂接一个JVM代理。
后面的篇章着重学习分析Spring的LTW和Spring AOP。