您的位置:首页 > 编程语言 > Java开发

Spring AOP---基础简介

2014-07-20 10:08 204 查看
       软件开发中,分布于应用中多处的功能被称为横切关注点,比如日志、安全和事务管理。这些横切关注点从概念上是与应用的业务逻辑相分离的,但是往往又直接嵌入到应用的业务逻辑中。将这些横切关注点与业务逻辑相分离正是面向切面编程(AOP)所要解决的。

       依赖注入有助于应用对象之间的解耦,而AOP可以实现横切关注点与它们所影响的对象之间的解耦。

       横切关注点可以被模块化为特殊的类,这些类被称为切面。这样做有两个好处:首先,每个关注点现在都只集中于一处,而不是分散到多处代码中;其次,服务模块更简洁,因为它们只包含主要关注点(或核心功能)的代码,而次要关注点的代码被转移到切面中了。

       1.AOP术语:

       >.通知(Advice):在AOP中,切面的工作被称为通知

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

Spring切面可以应用5种类型的通知:

       (1)Before---在方法被调用之前调用通知;

       (2)After---在方法完成之后调用通知,无论方法执行是否成功;

       (3)After-returning---在方法成功执行之后调用通知;

       (4)After-throwing---在方法抛出异常后调用通知;

       (5)Around---通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

       >.连接点(Joinpoint):连接点是在应用执行过程中能够插入切面的一个点

这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程中,并添加新的行为。

       >.切点(Poincut):一个切面并不需要通知应用的所有连接点。切点有助于缩小切面所通知连接点的范围。

切点的定义会匹配通知所要织入的一个或多个连接点。通常使用明确的类和方法名来指定这些切点,或是利用正则表达式定义匹配的类和方法名称模式来指定这些切点。

       >.切面(Aspect):切面是通知和切点的结合。通知和切点共同定义了关于切面的全部内容---它是什么,在何时和何处完成其功能。

       >.引入(Introduction):引入允许我们向现有的类添加新方法或属性。

       >.织入(Weaving):织入是将切面应用到目标对象来创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:

       (1)编译期---切面在目标类编译时被织入。需要特殊编译器。AspectJ的织入编译器就是以这种方式织入切面的。

       (2)类加载期---切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强目标类的字节码。

       (3)运行期---切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态创建一个代理对象。Spring AOP就是以这种方式织入切面的。

       2.Spring对AOP的支持

       创建切点来定义切面织入的连接点是AOP框架的基本功能。

       目前的AOP框架主要有:

        >.AspectJ(http://eclipse.org/aspectj);

        >.JBoss AOP(http://www.jboss.org/jbossaop);

        >.Spring AOP(http://www.springframework.org)。

        Spring提供了4中各具特色的AOP支持:

        >.基于代理的经典AOP;

        >.@AspectJ注解驱动的切面;

        >.纯POJO切面;

        >.注入式AspectJ切面(适合Spring各版本)。

        Spring通知是Java编写的。Spring在运行期通知对象:

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

         


      如上图所示,代理类封装了目标类,并拦截被通知的方法的调用,再将调用转发给真正的目标Bean。

       当拦截到方法调用时,在调用目标Bean方法之前,代理会执行切面逻辑。直到应用需要被代理的Bean时,Spring才创建代理对象。如果使用的是ApplicationContext,在ApplicationContext从BeanFactory中加载所有Bean时,Spring创建被代理的对象。因为Spring运行时才创建代理对象,所以不需要特殊的编译器来织入Spring AOP的切面。由于Spring基于动态代理,因此Spring只支持方法连接点。如果需要方法拦截之外的连接点拦截,可以利用AspectJ来协助Spring
AOP。

       3.使用切点选择连接点

       在Spring AOP中,使用AspectJ的切点表达式语言来定义切点。Spring仅支持AspectJ切点指示器的一个子集。

         


       在Spring中尝试使用AspectJ其他指示器时,会抛出IllegalArgumentException异常。另外,上述指示器中,只有execution指示器是唯一的执行匹配,其他的都是用于限制匹配的。这说明,execution指示器是我们编写切点定义时最主要使用的指示器。在此基础上,使用其他指示器来限制所匹配的切点。

          

           


           


          上面我们使用"&&"把execution和within指示器连在一起形成与关系,同样,可以使用"||"来表示或关系,使用"!"表示非关系。

        除了上面的指示器意外,Spring2.5引入了新的bean()指示器,使用该指示器,我们可以在切点表达式中使用Bean的ID来标识Bean。

         eg.

         execution(*  com.springaction.aop.domain.Perfomer.perform(..)) and bean(duke)

         上面的例子中,在执行 Perfomer 的 perform方法时应用通知,但限定Bean的ID为duke。

       4.在XML中声明切面

       


         5.注解切面

         使用注解创建切面是AspectJ 5引入的关键特性。使用AspectJ面向注解的模型可以非常简便的通过少量注解将人以类转变为切面。

       6.注入AspectJ切面

       虽然Spring AOP能满足许多应用的切面需求,但与AspectJ相比,Spring AOP扔是一个功能比较弱的AOP解决方案。AspectJ提供了Spring AOP所不能支持的许多类型的切点。

       下节会给出具体的配置demo。

       以上内容主要来自《Spring in action》的读书笔记。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息