简单地说, AOP 就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理 (Transactions) ,日志管理( logging, tracing, profiling and monitoring 记录跟踪 优化 校准),权限控制( Authentication ),同步 (Synchronization), 封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
实质上, AOP 只是 OOP 的一种补充或某种改进,它转换了编程的范式和视角,关注了一直以来被 OOP 忽 略或者说未能解决好的角落,使开发人员可以更好地将本不该彼此纠缠在一起的责任(如银行业务和事务处理)分离开来。通过面向切面的编程,可以将程序的责任 分开,对象与切面互不干扰。面向切面的模块并非显式地为对象所调用,而是通过或注入或截取的方式,去获得被封装的对象内部方法间的消息,然后做出相应地处 理。也许面向切面的模式破坏了对象的封装,却正其如此,方才能降低模块与模块之间的耦合度。同样地,通过对 “ 方面 ” 的封装,将这些通用的功能从不同的类中分离出来,使不同的模块都能共享同样的 “ 方面 ” ,这也极大地减少了重复代码。
Spring 的 AOP 核心技术还是动态代理, Spring 的代理实现方式有两种,默认使用 CGLIB ,也可以选择使用 JDK 的代理,这一切对开发人员来说是透明的,可以不关心这些。
以 Spring 为例:
1. 面( Aspect ): 一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是 J2EE 应用中一个关于横切关注点的很好的例子。 在 Spring AOP 中,切面可以使用通用类(基于模式的风格) 或者在普通类中以 @Aspect 注解( @AspectJ 风格)来实现。
2. 连接点( Joinpoint ): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在 Spring AOP 中,一个连接点 总是 代表一个方法的执行。 通过声明一个 org.aspectj.lang.JoinPoint 类型的参数可以使通知( Advice )的主体部分获得连接点信息。
3. 知( Advice ): 在切面的某个特定的连接点( Joinpoint )上执行的动作。通知有各种类型,其中包括 “around” 、 “before” 和 “after” 等通知。 通知的类型将在后面部分进行讨论。许多 AOP 框架,包括 Spring ,都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。
4. 切入点( Pointcut ) : 匹配连接点( Joinpoint )的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。 切入点表达式如何和连接点匹配是 AOP 的核心: Spring 缺省使用 AspectJ 切入点语法。
5. 引入( Introduction ) : (也被称为内部类型声明( inter-type declaration ))。声明额外的方法或者某个类型的字段。 Spring 允许引入新的接口(以及一个对应的实现)到任何被代理的对象。 例如,你可以使用一个引入来使 bean 实现 IsModified 接口,以便简化缓存机制。
6. 目标对象( Target Object ) : 被一个或者多个切面( aspect )所通知( advise )的对象。也有人把它叫做 被通知(advised) 对象。 既然 Spring AOP 是通过运行时代理实现的,这个对象永远是一个 被代理(proxied) 对象。
7.AOP 代理( AOP Proxy ) : AOP 框架创建的对象,用来实现切面契约( aspect contract )(包括通知方法执行等功能)。 在 Spring 中, AOP 代理可以是 JDK 动态代理或者 CGLIB 代理。 注意: Spring 2.0 最新引入的基于模式( schema-based )风格和 @AspectJ 注解风格的切面声明,对于使用这些风格的用户来说,代理的创建是透明的。
8. 织入( Weaving ) : 把切面( aspect )连接到其它的应用程序类型或者对象上,并创建一个被通知( advised )的对象。 这些可以在编译时(例如使用 AspectJ 编译器),类加载时和运行时完成。 Spring 和其他纯 Java AOP 框架一样,在运行时完成织入。
通知的类型:
1. 前置通知( Before advice ) : 在某连接点( join point )之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
2. 返回后通知( After returning advice ) : 在某连接点( join point )正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
3. 抛出异常后通知( After throwing advice ) : 在方法抛出异常退出时执行的通知。
4. 后通知( After (finally) advice ) : 当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
5. 环绕通知( Around Advice ) : 包围一个连接点( join point )的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。