zoukankan      html  css  js  c++  java
  • Spring AOP 面向切面编程

    AOP

    在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

    在Spring中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

    AOP使用场景

    • Authentication 权限
    • Caching 缓存
    • Context passing 内容传递
    • Error handling 错误处理
    • Lazy loading 懒加载
    • Debugging  调试
    • logging, tracing, profiling and monitoring 记录跟踪 优化 校准
    • Performance optimization 性能优化
    • Persistence  持久化
    • Resource pooling 资源池
    • Synchronization 同步
    • Transactions 事务

    AOP的术语

    1. 通知(Advice):

    通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。

    通知就是切面中除去切点之外的部分。如在方法执行前触发,执行后触发,异常时触发,以及触发那个方法。

    2.连接点(Joinpoint):

    程序能够应用通知的一个"时机",这些"时机"就是连接点,例如方法被调用时、异常被抛出时等等。

    连接点是通知的一部分。

    3.切入点(Pointcut)

    通知定义了切面要发生的"故事"和时间,那么切入点就定义了"故事"发生的地点,例如某个类或方法的名称,spring中允许我们方便的用正则表达式来指定

    切入点定义在哪些类的那些方法上执行。

    4.切面(Aspect)

    通知和切入点共同组成了切面:时间、地点和要发生的"故事"

    切面就时被标注了@Aspect注解的整个类要做的功能。包含定义切点,连接点,以及要触发的操作。

    5.引入(Introduction)

    引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)

    6.目标(Target)

    即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事)

    目标是概念吧 不应该有目标这种配置 因为目标是在切点里通过表达式配置的。

    7.代理(proxy)

    应用通知的对象,详细内容参见设计模式里面的代理模式

    这也是个概念,是内部实现的逻辑。代理是spring为了实现AOP为采用的一种方式。

    8.织入(Weaving)

    把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:

    (1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器

    (2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码

    (3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

    看看另外一种解释,更加通俗易懂:

    • 什么是面向切面编程

    横切关注点:影响应用多处的功能(安全、事务、日志)

    • 切面:

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

    优点:

    每个关注点现在都集中于一处,而不是分散到多处代码中 
    服务模块更简洁,服务模块只需关注核心代码。

    AOP 术语

    • 通知: 

    定义:切面也需要完成工作。在 AOP 术语中,切面的工作被称为通知。

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

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

    Before——在方法调用之前调用通知

    After——在方法完成之后调用通知,无论方法执行成功与否

    After-returning——在方法执行成功之后调用通知

    After-throwing——在方法抛出异常后进行通知

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

    • 连接点: 

    定义:连接点是一个应用执行过程中能够插入一个切面的点。

    连接点可以是调用方法时、抛出异常时、甚至修改字段时、

    切面代码可以利用这些点插入到应用的正规流程中

    程序执行过程中能够应用通知的所有点。

    • 切点: 

    定义:如果通知定义了"什么"和"何时"。那么切点就定义了"何处"。切点会匹配通知所要织入的一个或者多个连接点。

    通常使用明确的类或者方法来指定这些切点。

    作用:定义通知被应用的位置(在哪些连接点)

    • 切面: 

    定义:切面是通知和切点的集合,通知和切点共同定义了切面的全部功能——它是什么,在何时何处完成其功能。

    • 引入: 

    引入允许我们向现有的类中添加方法或属性

    • 织入: 

    织入是将切面应用到目标对象来创建的代理对象过程。

    切面在指定的连接点被织入到目标对象中,在目标对象的生命周期中有多个点可以织入

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

    类加载期——切面在类加载到

    JVM ,这种方式需要特殊的类加载器,他可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5 的 LTW 就支持这种织入方式

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

     

    Spring提供了4种实现AOP的方式:

    1. 经典的基于代理的AOP 这种已经过时了
    2. 纯POJO切面 通过xml配置aop来实现切面 java类就是纯pojo
    3. @AspectJ注解驱动的切面 通过Aspect注解来实现aop,只是使用AspectJ的注解,内部实现仍然是基于代理的。
    4. 注入式AspectJ切面 这个就是使用AspectJ了。上面三种都是spring aop的变体,也就是基于动态代理的aop。所以无法拦截如属性和构造器这种特殊的部分,如果有这种需求,要使用注入式AspectJ切面。

    可以说上面123是Spring的AOP,第4个是AspectJ的了。关于Spring的AOP:

    • Spring的通知是java类编写的。AspectJ需要学习它自定义的语法。
    • Spring在运行时通知对象,而且不需要特殊的编译器来织入Spring AOP。
    • Spring只支持方法级别的连接点。

    Spring 使用AspectJ的切点表达式来定义切面:

    AspectJ 指示器

    描述

    arg ()

    限制连接点的指定参数为指定类型的执行方法

    @args ()

    限制连接点匹配参数由指定注解标注的执行方法

    execution ()

    用于匹配连接点的执行方法

    this ()

    限制连接点匹配 AOP 代理的 Bean 引用为指定类型的类

    target ()

    限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型注解

    within()

    限制连接点匹配指定类型

    @within()

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

    @annotation

    限制匹配带有指定注释的连接点

    1. 创建自己的切点 
     
    - execution( ) 指示器选择 Instrument 的 play( ) 方法。 
    方法表达式是以 * 号开头,标识了我们不关心的方法返回值的类型。 
    * 后我们指定了权限定类名和方法名。 
    对于方法的参数列表,使用(..)标识切点选择任意的 play( ) 方法,无论入参是什么。 
    - 假设我们需要匹配切点仅匹配 com.Springinaction.springidol 包。可以使用 within() 
     
    注意 && 是将 execution( ) 和 within( ) 连接起来,形成的 and 关系。同理也可以使用 || 或关系、!非关系 
    - 创建 spring 的 bean( ) 指示器 
    Spring 2.5 引入一个新的 bean( ) 指示器,该指示器允许我们在切点表达式中使用 Bean ID 来标识 Bean 
    bean( ) 使用 Bean ID 或 Bean 名称作为参数来限制切点只匹配特定 Bean。 
    如下,我们希望执行 Instrument 的 play( ) 方法时候应用通知,但限定 Bean 的 ID 为 eddie 
     
    还可以使用非操作作为除了指定 ID 的 Bean 以外的其他 Bean应用通知 
     
    在此场景下,切面会通知被编织到所有 ID 不为 eddie 的 Bean 中

     

  • 相关阅读:
    document.body.clientHeight 和 document.documentElement.clientHeight 的区别
    Javascript操作div及其内含对象示例
    面向对象分析设计的经验原则
    翻页控件示例代码
    C#的6种常用集合类示例
    UML基础知识
    重温OSI和TCP/IP网络分层
    设计模式总结
    活用设计模式
    GridView当数据源为空时仍显示表头
  • 原文地址:https://www.cnblogs.com/xiaolang8762400/p/7020525.html
Copyright © 2011-2022 走看看