【Spring系列】Spring AOP面向切面编程

前言

接上一篇文章,在上午中使用了切面作防重复控制,本文着重介绍切面AOP。spring

在开发中,有一些功能行为是通用的,好比、日志管理、安全和事务,它们有一个共同点就是分布于应用中的多处,这种功能被称为横切关注点(cross-cutting concerns)。编程

DI(依赖注入)有助于应用对象之间的解耦,而AOP能够实现横切关注点与他们所影响的对象之间的解耦。安全

面向切面编程在Spring AOP中有4种类型的调用,方法调用的以前、后、异常增长其余方法,方法调用的前和后调用其余方法,将方法中的参数传递给其余方法,讲一个崭新额的接口实现做为父类接口给其余方法所属的方法。咱们在调用某个方法的时候,Spring AOP在其余勒种就为这个方法额外作了其余事情。ide

1、什么是面向切面编程?

继承和委托是最多见的实现通用功能的面向对象技术,切面提供了取代继承和委托的另外一种选择,并且在不少场景下更清晰简洁。模块化

在使用面向切面编程时,咱们仍然在一个地方定义通用功能,可是咱们能够提供声明的方式定义这个功能以何种方式在何处应用,而无需修改受影响的类,this

横切关注点能够被模块化为特殊的类,这些类被称为切面。spa

2、切面术语:通知、链接点和切点、切面

切面是一个类,这个可的做用是完成对指定位置的指定动做的附属动做,指定位置首先有一个选择范围,能够是建立对象、方法调用、变量改变等等,这些选择范围就是链接点,你能够决定选取其中的一部分,这些被选中的部分就是切点,固然选择的过程在代码中实现,选好点后,一旦这些点被运行了,好比调用了一个类,切面里的类中的某个方法就会被调用,以完成别的功能,这个被调用的方法就是通知。代理

即:日志

  • 切面:类
  • 切点:切面关注的指定代码的动做链接点:能够做为切点的代码动做
  • 通知:方法,切点处额外多出的方法
  • 链接点:切点的代码动做

一、通知(Advice) 5种类型xml

切面的工做被称为通知

通知定义了切面的什么以及什么时候使用,除了描述切面要完成的工做,通知还解决了什么时候执行这个工做的问题。

根据应用于方法以前、后、先后、异常等能够分为

  • Before:在方法调用前调用通知
  • After:在方法被调用以后调用通知,不管方法是否执行成功
  • After-returning:在方法成功执行以后调用通知
  • After-throwing:在方法抛出异常后调用通知
  • Around:方法被调用以前和调用以后个执行一次自定义的行为

二、链接点(Joinpoint)

链接点是在应用执行过程当中可以插入切面的一个点,准确的说是程序运行中的某种时机,好比调用方法时,抛出异常时、甚至是修改一个字段时。切面代码能够利用这些点(时机)插入到应用的正常流程之中,并添加新的行为。

三、切点(Pointcut)

一个切面仅仅须要通知有限的链接点而不是所有的链接点,切点定义了链接点中的哪些是通知须要产生做用的,

切点会匹配通知所要织入的一个或者多个链接点

咱们一般使用明确的类和方法名称来指定这些切点

简单的说,切点是相对于不一样通知而言的有效链接点的集合

四、切面(Aspect)

切面是通知和切点的集合,通知决定作什么?什么时候?切点决定在那些地方进行通知。

五、引入(Introduction)

引入是一个过程的描述,指咱们向现有的类添加新方法或属性。咱们能够把一个类做为通知,引入到被通知的类中,从而在不改变被通知的类的状况下改变这个类。

六、织入(Weaving)

切面在指定的链接点(即通知在切点通知被通知的方法,通知被引入了被通知的类)被织入到目标对象中,括号中一直说被通知类增长了方法,这种增长的方法就是织入,说到底,织入是为被通知类建立了代理类,在代理类中增长了方法。从表面看来,被代理类增长了方法,即织入。

织入是将切面应用到目标对象来建立新的代理对象的过程。切面在指定的链接点被织入到目标对象中。

在目标对象的多个点能够进行织入。

经过在代理类中包裹切面,Spring在运行期将切面织入到Spring管理的Bean中。

编译期——切面在目标类编译时被织入。

·这种方式须要特殊的编译器。

·AspectJ的织入编译器就是以这种方式织入切面的。

类加载期——切面在目标类加载到JVM时被织入。

·这种方式须要特殊的类加载器(ClassLoader),它能够在目标类被引入应用以前加强该目标类的字节码。

·AspectJ 5的LTW(load-time weaving)就支持以这种方式织入切面。

运行期——切面在应用运行期间的某个时段被织入。

·通常状况下,在织入切面时,AOP容器会为目标对象动态地建立一个代理对象。

·Spring AOP 就是在运行期,为目标对象动态建立一个代理对象来实现织入的。当拦截到方法调用时。在调用目标Bean以前,代理会执行切面逻辑。直到应用须要被代理的Bean时,Spring才建立代理对象。

 

3、Spring对AOP的支持

一、Spring提供了4种各具特点的AOP支持

  • 基于代理的经典AOP;
  • @AspectJ注解驱动的切面;
  • 纯POJO切面;
  • 注入式AspectJ切面(适合Spring各版本)。

前3种都是Spring基于代理的AOP变体,所以,Spring对AOP的支持局限于方法拦截。若是AOP需求超过了简单方法拦截的范畴(如构造器或属性拦截),那么应该考虑在AspectJ里实现切面,利用Spring的DI(依赖注入)把Spring Bean注入到AspectJ切面中:

二、Spring只支持方法链接点

AspectJ和Jboss除了方法切点,还提供了字段和构造器接入点。因此,单单使用Spring咱们没法构建细粒度的通知,也没法使用构造器链接点。对于这种状况,咱们能够利用Aspect来协助Spring AOP。

三、切点规定了那些链接点

咱们使用切点来选择链接点,而后是不一样的通知匹配不一样的切点。在Spring AOP中,须要使用AspectJ的切点表达式来定义切点。

四、Spring AOP所支持的AspectJ切点指示器

arg() 限制链接点匹配参数为指定类型的执行方法

@args() 限制链接点匹配参数由指定注解标注的执行方法

execution() 用于匹配是链接点的执行方法

this() 限制链接点匹配AOP代理的Bean引用为指定类型的类

target() 限制链接点匹配目标对象为指定类型的类

@target() 限制链接点匹配特定的执行对象,这些对象对应的类要具有指定类型的注解

within() 限制链接点匹配指定的类型

@within() 限制链接点匹配指定注解所标注的类型(当使用Spring AOP时,方法定义在由指定的注解所标注的类里)

@annotation 限制匹配带有指定注解链接点

只有execution切点指示器是惟一的执行匹配,而其余的切点指示器都是用于限制匹配的。

五、编写切点,这些最后被添加到xml配置文件中

注意:所写的路径都是接口类的路径,切点是在接口类中而不是具体的实现类中的。

不关注返回类型,不关注入参类型,在方法执行的时候引入切点

execution(* com.springination.springidol.Instrument.play(..))

 

增长限制-而且限定了切点的包路径(后者是多余的吗?)

execution(* com.springination.springidol.Instrument.play(..))

and within(com.springinaction.springidol.*)

 

在spring2.5以后,能够经过id来限定bean

execution(* com.springination.springidol.Instrument.play(..))

and within(com.springinaction.springidol.*)

and bean(eddie)

 

固然也可使用反向操做

execution(* com.springination.springidol.Instrument.play(..))

and within(com.springinaction.springidol.*)

and bean(eddie)

and !bean(eddie2)

六、在XML中声明切面

AOP配置元素 描述

<aop:advisor> 定义AOP通知器

<aop:after> 定义AOP后置通知(无论被通知的方法是否执行成功)

<aop:after-returning> 定义AOP after-returning通知

<aop:after-throwing> 定义after-throwing通知

<aop:around> 定义AOP环绕通知

<aop:aspect> 定义切面

<aop:aspect-autoproxy> 启用@AspectJ注解驱动的切面

<aop:before> 定义AOP前置通知

<aop:config> 顶层的AOP配置元素。大多数的<AOP:*>元素,必须包含在 <aop:config>元素内

<aop:declare-parents> 为被通知的对象引入额外的接口,并透明地实现

<aop:pointcut> 定义切点

相关文章
相关标签/搜索