AOP(Aspect-Oriented Programming,面向切面编程),能够说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来创建一种对象层次结构,用以模拟公共行为的一个集合。当咱们须要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP容许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码每每水平地散布在全部对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其余类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它致使了大量代码的重复,而不利于各个模块的重用。正则表达式
而AOP技术则偏偏相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即切面。所谓“切面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减小系统的重复代码,下降模块间的耦合度,并有利于将来的可操做性和可维护性。AOP表明的是一个横向的关系,若是说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向切面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以得到其内部的消息。而剖开的切面,也就是所谓的“切面”了。而后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。express
使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特色是,他们常常发生在核心关注点的多处,而各处都基本类似。好比权限认证、日志、事务处理。Aop 的做用在于分离系统中的各类关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”编程
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法建立“切面”,从而使得编译器能够在编译期间织入有关“切面”的代码。然而异曲同工,实现AOP的技术特性倒是相同的,分别为:安全
一、join point(链接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不须要去定义一个join point。
二、point cut(切入点):本质上是一个捕获链接点的结构。在AOP中,能够定义一个point cut,来捕获相关方法的调用。
三、advice(通知):是point cut的执行代码,是执行“切面”的具体逻辑。
四、aspect(切面):point cut和advice结合起来就是aspect,它相似于OOP中定义的一个类,但它表明的更可能是对象间横向的关系。
五、introduce(引入):为对象引入附加的方法或属性,从而达到修改对象结构的目的。有的AOP工具又将其称为mixin。app
六、AOP代理(AOP Proxy):AOP框架建立的对象,这个对象一般能够做为目标对象的替代品,而AOP代理提供比目标对象更增强大的功能。真实的情形是,当应用调用AOP代理的方法时,AOP代理会在本身的方法中回调目标对象的方法,从而完成应用的调用。关于AOP代理的典型例子就是Spring中的事务代理Bean。一般,目标Bean的方法不是事务性的,而AOP代理包含目标Bean的所有方法,并且这 些方法通过增强变成了事务性方法。简单地说,目标对象是蓝本,AOP代理是目标对象的增强,在目标对象的基础上,增长属性和方法,提供更强大的功能。
目标对象包含一系列切入点。切入点能够触发处理链接点集合。用户能够本身定义切入点,如使用正则表达式。AOP代理包装目标对象,在切入点处加入处理。在切入点加入的处理,使得目标对象的方法功能更强。Spring 默认使用JDK动态代理实现AOP代理,主要用于代理接口。也可使用CGLIB代理。实现类的代理,而不是接口。若是业务对象没有实现接口,默认使用 CGLIB代理。但面向接口编程是良好的习惯,尽可能不要面向具体类编程。所以,业务对象一般应实现一个或多个接口。框架
七、目标对象(Target Object):包含一个链接点的对象,也被称为代理对象。
八、 前置通知(Before advice):在某链接点(JoinPoint)以前执行的通知,但这个通知不能阻止链接点前的执行。ApplicationContext中在<aop:aspect>里面使用<aop:before>元素进行声明。
九、后通知(After advice) :当某链接点退出的时候执行的通知(不管是正常返回仍是异常退出)。ApplicationContext中在<aop:aspect>里面使用<aop:after>元素进行声明。
十、返回后通知(After return advice) :在某链接点正常完成后执行的通知,不包括抛出异常的状况。ApplicationContext中在<aop:aspect>里面使用<after-returning>元素进行声明。
十一、环绕通知(Around advice) :包围一个链接点的通知,相似Web中Servlet规范中的Filter的doFilter方法。能够在方法的调用先后完成自定义的行为,也能够选择不执行。ApplicationContext中在<aop:aspect>里面使用<aop:around>元素进行声明。工具
十二、抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。 ApplicationContext中在<aop:aspect>里面使用<aop:after-throwing>元素进行声明。spa
Spring2.0目前只支持使用方法调用做为链接点(join point)。设计
Spring 定义切入点语法:excution(modifiers-pattern?ret-type-pattern declaring-type-pattern ?name-pattern(param-pattern)throws-pattern?)代理
除了ret-type-pattern (即返回类型模式)、name-pattern(param-pattern)(名字模式和参数模式)外,其余模式都是可选的。返回类型模式决定了方法的返回类型必须依次匹配一个链接点(即一个方法)。使用最频繁的一个返回类型模式是*,它表明了匹配任意的返回类型。若是写明了返回类型,好比String,那么只能匹配返回String类型的链接点(方法)。名字模式匹配的是方法名。你能够用*通配符表示匹配全部方法名。参数模式中,()表示匹配了不接受任何参数的方法,而(。。)表示匹配任意数量参数的方法。模式(*)表示匹配任意类型参数的方法。模式(*,String)表示匹配:第一个为任意参数类型,第二个必须为String类型的方法。
modifiers-pattern:方法的操做权限
ret-type-pattern:返回值
declaring-type-pattern:方法所在的包
name-pattern:方法名
parm-pattern:参数名
throws-pattern:异常
下面是定义切入点的例子:
。任意公共方法的执行:
excution(public * *(。。))
。任何一个以set开头的方法执行:
excution(* set*(。。))
。AccountService接口的任意方法的执行:
excution(* com.xyz.service.AccountService.*(。。))
。定义在service包的任意方法的执行:
excution(* com.xyz.service.*.*(。。))
。定义在service包或子包的任意方法的执行:
excution(* com.xyz.service..*.*(。。))
在Spring配置文件里,全部的切面和通知器都要配置在<aop:config>标签里,一个applicationContext能够包含多个<aop:config>,一个<aop:config>能够包含pointcut、advisor、aspect元素(注意必须是这个顺序)。
一、声明一个切面
<aop:config>
<aop:aspect id="myAspect" ref="myBean">
。。。。。
</aop:aspect>
</aop:config>
<bean id="myBean" class="">
。。。。。
</Bean>
说明:切面用<aop:aspect>来声明,backing bean(支持bean)用ref引用。
二、声明一个切入点
<aop:config>
<aop:pointcut id="myPointcut" expression="excution(* com.service.*.*(..))"/>
</aop:config>
三、声明一个通知
Spring2.0经过<aop:advisors>元素来支持advisors概念,大多数状况下,它将和transaction advice一块儿使用,格式以下:
<aop:config>
<aop:pointcut id="myService" expression="excution(* com.xyz.service.*.*(..))"/>
<aop:advisors pointcut-ref="myService" advice-ref="tx-advice"/>
</aop:config>
<txt:advice id="tx-advice">
<tx:attributes>
<tx:method name="inser*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="updat*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="delet*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="process*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</txt:advice>
说明:advisors 执行切入点方法时都要执行advice-ref引用的事务处理