引言
AOP(Aspected Oriented Programming)是一种新兴的编程技术它可以解决OOP和过程化方法不能够很好解决的横切(crosscut)问题如事务安全日志等横切关注当未来系统变得越来越复杂横切关注点就成为一个打问题的时候AOP就可以很轻松的解决横切关注点这个问题使得AOP编程成为Spring 是基于JEE的轻量级开源开发框架其中Spring AOP组件实现了面向方面编程
AOP 概述
面向方面编程 (AOP) 提供从另一个角度来考虑程序结构以完善面向对象编程(OOP) 面向对象将应用程序分解成各个层次的对象而AOP将程序分解成各个方面或者说关注点 这使得可以模块化诸如事务管理等这些横切多个对象的关注点
AOP 基本概念
方面(Aspect) 一个关注点的模块化这个关注点实现可能另外横切多个对象事务管理是JEE应用中一个很好的横切关注点例子方面用Spring的 Advisor或拦截器实现
连接点(Joinpoint) 程序执行过程中明确的点如方法的调 用或特定的异常被抛出
通知(Advice) 在特定的连接点AOP框架执行的动作各种类 型的通知包括aroundbefore和throws通知通知类型将在下面讨论许多AOP框架 包括Spring都是以拦截器做通知模型维护一个围绕连接点的拦截器链
切入点(Pointcut) 指定一个通知将被引发的一系列连接点 的集合AOP框架必须允许开发者指定切入点例如使用正则表达式
引入(Introduction) 添加方法或字段到被通知的类 Spring允许引入新的接口到任何被通知的对象例如你可以使用一个引入使任何对象实现 IsModified接口来简化缓存
目标对象(Target Object) 包含连接点的对象也被称作 被通知或被代理对象
AOP代理(AOP Proxy) AOP框架创建的对象包含通知 在Spring中AOP代理可以是JDK动态代理或者CGLIB代理
织入(Weaving) 组装方面来创建一个被通知对象这可以在编译时 完成(例如使用AspectJ编译器)也可以在运行时完成Spring和其他纯Java AOP框架一样 在运行时完成织入
Spring AOP 介绍
Spring的一个关键组件就是AOP框架 Spring IoC容器(BeanFactory 和ApplicationContext)并不依赖于AOP 这意味着如果你不需要使用AOP可以不用AOP完善了Spring IoC使之成为一个有效的中间件解决方案
Spring AOP 是Spring 框架的重要组成部分它实现了AOP联盟约定的接口Spring AOP 是由纯Java开发完成的Spring AOP 只实现了方法级别的连接点在JEE应用中AOP拦截到方法级的操作已经足够OOP倡导的是基于setter/getter 的方法访问而非直接访问域而Spring 有足够理由仅仅提供方法级的连接点为了使控制反转(IoC)很方便的使用到非常健壮灵活的企业服务则需要Spring AOP 的实现Spring AOP 在运行时才创建Advice 对象Spring AOP的优点如下
允许开发者使用声明式企业服务比如事务服务安全性服务
开发者可以开发满足业务需求的自定义方面
开发Spring AOP Advice 很方便可以借助代理类快速搭建Spring AOP 应用
使用Spring AOP松散耦合
创建通知
为实现AOP开发者需要开发AOP 通知(Advice)AOP 通知(Advice) 包含了方面(Aspect)的逻辑当创建一个Advice 对象的时候你就编写了实现横切(crosscutting)功能 Spring 的连接点是用方法拦截器实现的这就意味着你编写的Spring AOP 通知将在方法调用的不同点组入进程序中由于在调用一个方法时有几个不同的时间点Spring 可以在不同的时间点组入进程序Spring AOP中提供了四种通知的接口 MethodBeforeAdvice 用于在目标方法调用前触发AfterReturningAdvice 用于在目标方法调用后触发 ThrowsAdvice 用于在目标方法抛出异常时触发MethodInterceptor 用于实现 Around 通知(Advice)在目方法执行的前后触发
如果要实现相应功能则需要实现上述对应的接口例如实现Before 通知(Advice)需要实现方法 void before(Method method Object[] args Object target) 实现 After 通知(Advice) 需要实现方法 void afterReturning (Method method Object[] args Object target)
在Spring 中定义切入点
在不能明确调用方法的时候通知就很不实用切入点则可以决定特定的类特定的方法是否匹配特定标准如果某匹配则通知将应用到此方法上Spring 切入点允许用很灵活的方式将通知组织进我们的类中Spring 中的切入点框架的核心是Pointcut接口此接口允许我们定义组入通知中的类和方法许多方面是通过一系列的通知和切入点组合来定义
在Spring中一个advisor就是一个方面的完整的模块化表示Spring提供了PointcutAdvisor接口把通知和切入点组合成一个对象Spring中很多内建的切入点都有对应的PointcutAdvisor这使得你可以很方便在一个地方管理切入点和通知Spring中的切入点分为两类静态和动态因为静态切入点的性能要优于动态切入点所以优先考虑使用Spring 为我们提供创建静态切入点很实用的类StaticMethodMatherPointcut在这个类中我们只需要关心setMappedName和setMappedNams方法你可以使用具体的类名也可以使用通配符如设置mappedName属性为set* 则匹配所有的set方法Spring还提供了另通过正则表达式来创建静态切入点的实用类RegexpMethodPointcut通过使用Perl样式的正则表达式来定义你感兴趣的方法当切入点需要运行时参数值来执行通知时这时就需要使用动态切入点Spring提供了一个内建的动态切入点ControlFlowPointcut此切入点匹配基于当前线程的调用堆栈我们可以在只有在当前线程执行的执行时找到特定的类和特定的方法才返回true使用动态切入点有很大的性能损耗大多数的切入点可以静态确定我们很少有机会创建动态切入点为了增加可切入点的可重用性Spring 提供了切入点上的集合操作交集和合并
用ProxyFactoryBean创建AOP代理
ProxyFactoryBean和其他Spring的 FactoryBean实现一样引入一个间接的层次如果你定义一个名字为myfactory的ProxyFactoryBean 引用myfactory的对象所看到的不是ProxyFactoryBean 实例本身而是由实现ProxyFactoryBean的类的 getObject()方法所创建的对象这个方法将创建一个包装了目标对象 的AOP代理使用ProxyFactoryBean或者其他IoC可知的类来创建AOP代理的最重要的优点之一是IoC可以管理通知和切入点这是一个非常的强大的功能能够实现其他AOP框架很难实现的特定的方法例如一个通知本身可以引用应用对象(除了目标对象 它在任何AOP框架中都可以引用应用对象)这完全得益于依赖注入所提供的可插入性通常我们不需要ProxyFactoryBean的全部功能因为我们常常只对一个方面感兴趣 例如事务管理当我们仅仅对一个特定的方面感兴趣时我们可以使用许多便利的工厂来创建AOP代理如TransactionProxyFactoryBean
自动代理
在应用较小时只有很少类需要被通知的时ProxyFactoryBean 可以很好的工作当有许多类需要通知的时显示的创建每个代理就显得很繁琐幸运的是Spring提供了是使用自动通过容器来创建代理这时就只需要配置一个Bean来做繁琐的工作Spring提供了两个类实现自动代理BeanNameAutoProxyCreator和DefaultAdvisorAutoProxyCreator
BeanNameAutoProxyCreator为匹配名字的Bean产生代理它可以使用在将一个或者多个方面应用在命名相似的Bean中自动代理框架假设代理将要暴露出什么接口如果目标Bean没有实现任何接口这时就会动态产生一个子类而更强大的自动代理是DefaultAdvisorAutoProxyCreator你所需要做的是在BeanFactory中包含它的配置这个类的奇妙之处在于他使用实现了BeanPostProcessor接口在Bean定义被加载倒Spring容器中后DefaultAdvisorAutoProxyCreator将搜索上下文中的Advisor最后它将Advisor应用到匹配Advisor切入点的Bean中这个代理只对Advisor起作用它需要通过Advisor来得到需要通知的Bean元数据自动代理(MetaData AutoProxy)元数据自动代理配置依赖于源代码属性而不是外部XML配置文件这可以非常方便的使源代码和AOP元数据组织在同一个地方元数据自动代理最常用的地方是用来声明事务Spring提供了很强的框架来通过AOP框架来声明事务这提供了在EJB使用声明式事务的相同功能
结论
AOP 是面向对象编程的有力补充通过方面就可以聚合在应用中行为形成可重用模块
通过程序可以实现怎样和在什么地方来调用这些行为这可以减少代码重复并使你更加关注业务逻辑Spring 提供了AOP框架来实现调用方法时加入方面在AOP框架中可以很方便的使用预定义的静态切入点来定义被调用的类和方法我们需要通过Spring提供的代理类来产生代理对象可以使用ProxyFactoryBean也可以使用自动代理Spring AOP 的编程方式模块化了横向关注点的实现提供了一个更好更快的软件开发方式在软件结构日益扩大结构日益复杂的今天Spring AOP 将会发挥越来越重要的作用