Part III. 核心技术-11. Spring面向切面编程-11.1 介绍

面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP)。 OOP模块化的关键单位是类,而在AOP中,模块化单位是方面。 切面使得可以模块化诸如跨多个类型和对象的事务管理等问题。 (这种关注在AOP文献中通常被称为横切关注点。)

Spring的关键组件之一是AOP框架。 虽然Spring IoC容器不依赖于AOP,这意味着如果您不想使用AOPAOP将补充Spring IoC以提供非常强大的中间件解决方案。

Spring 2.0 AOP

Spring 2.0引入了使用基于模式的方法或@AspectJ注释样式来编写自定义方面的更简单和更强大的方法。 这两种风格都提供>了全面的建议和使用AspectJ切入点语言,同时仍然使用Spring AOP进行编织。

本章讨论了基于Spring 2.0 Schema和@ AspectJAOP支持。 Spring 2.0 AOPSpring 1.2 AOP保持完全向后兼容,Spring 1.2 API提供的低级AOP支持将在下一章讨论。

在Spring框架中使用AOP …

  • …提供声明式企业服务,特别是作为EJB声明性服务的替代品。 最重要的这种服务是声明式事务管理。
  • …允许用户实现自定义方面,补充他们使用OOPAOP

如果您只对通用声明性服务或其他预先打包的声明性中间件服务(如池)感兴趣,则不需要直接使用Spring AOP,并且可以跳过本章的大部分内容。

11.1.1 AOP概念

我们首先定义一些中央AOP概念和术语。 这些术语不是Spring特定的…不幸的是,AOP术语不是特别直观的; 然而,如果Spring使用自己的术语,会更加混乱。

  • 切面:跨越多个类的关注模块化。 事务管理是企业Java应用程序中横向关注的一个很好的例子。 在Spring AOP中,使用常规类(基于模式的方法)或使用@Aspect注解(@AspectJ样式)注解的常规类来实现方面。
  • 联接点:程序执行过程中的一点,例如执行方法或处理异常。 在Spring AOP中,连接点总是表示方法的执行。
  • 通知:特定连接点的方面采取的行动。 不同类型的建议包括“周围”,“之前”和“之后”咨询。 (建议类型将在下面讨论。)许多AOP框架(包括Spring)将建议作为拦截器建模,在连接点周围维护一系列拦截器。
  • 切入点:匹配连接点的谓词。 建议与切入点表达式相关联,并在与切入点匹配的任何连接点运行(例如,执行具有特定名称的方法)。 连接点与切入点表达式匹配的概念是AOP的核心,默认情况下Spring使用AspectJ切入点表达式语言。
  • 简介:代表类型声明附加的方法或字段。 Spring AOP允许您向任何建议的对象引入新的接口(以及相应的实现)。 例如,您可以使用简介来实现一个Bean实现IsModified接口,以简化缓存。 (介绍被称为AspectJ社区中的类型间声明。)
  • 目标对象:由一个或多个方面建议的对象。 也称为建议对象。 由于Spring AOP是使用运行时代理实现的,因此该对象将始终是一个代理对象。
  • AOP代理:由AOP框架创建的一个对象,以实现方面的合同(建议方法执行等)。 在Spring框架中,AOP代理将是JDK动态代理或CGLIB代理。
  • 织入:与其他应用程序类型或对象链接方面以创建建议的对象。 这可以在编译时完成(例如使用AspectJ编译器),加载时间或运行时。 与其他纯Java AOP框架一样,Spring AOP在运行时执行编织。

通知类型:

  • 前置通知:在连接点之前执行的通知,但是没有能力阻止执行流程进行到连接点(除非引发异常)。
  • 后置返回通知:在连接点正常完成后要执行的通知:例如,如果方法返回而不抛出异常。
  • 后置异常通知:如果方法通过抛出异常退出,则执行的建议。
  • 后置最终通知:通知执行,无论连接点退出的方式(正常或异常返回)。
  • 环绕通知:围绕连接点的建通知,如方法调用。 这是最强大的通知。 周围的通知可以在方法调用之前和之后执行自定义行为。 它还负责选择是否继续进行连接点,或者通过返回自己的返回值或抛出异常来快速建立方法执行。

环绕通知是最一般的通知。由于Spring AOP(像AspectJ)提供了全面的通知类型,我们建议您使用能够实现所需行为的最不实用的通知类型。例如,如果您只需要使用方法的返回值来更新缓存,那么最好是实现一个后置返回通知而不是一个环绕通知,尽管环绕通知可以完成相同的事情。使用最具体的通知类型提供了一个更简单的编程模型,具有较少的错误潜力。例如,您不需要在JoinPoint上调用proceed()方法,用于环绕通知,因此无法调用它。

在Spring 2.0中,所有的建议参数都是静态类型的,因此您可以使用适当类型的建议参数(例如方法执行中的返回值的类型),而不是Object数组。

连接点的概念,与切入点匹配是AOP的关键,它与仅提供截取的旧技术区分开来。切入点使得建议能够独立于面向对象层次结构。例如,提供声明性事务管理的周围建议可以应用于跨越多个对象(例如服务层中的所有业务操作)的一组方法。

11.1.2 Spring AOP功能和目标

Spring AOP在纯Java中实现。 不需要特殊的编译过程。 Spring AOP不需要控制类加载器层次结构,因此适用于Servlet容器或应用程序服务器。

Spring AOP目前仅支持方法执行连接点(建议在Spring bean上执行方法)。 现场拦截是没有实现的,虽然可以添加对现场拦截的支持,而不会破坏核心的Spring AOP API。 如果您需要建议现场访问和更新连接点,请考虑使用AspectJ等语言。

Spring AOP的AOP方法与大多数其他AOP框架的方法不同。目的不是提供最完整的AOP实现(尽管Spring AOP非常有能力);而是提供AOP实现和Spring IoC之间的紧密集成,以帮助解决企业应用程序中的常见问题。

因此,例如,Spring Framework的AOP功能通常与Spring IoC容器一起使用。方面使用普通的bean定义语法进行配置(尽管这样可以实现强大的“自动转换”功能):这与其他AOP实现是一个重要的区别。有些事情您不能轻松或高效地使用Spring AOP,例如建议非常细粒度的对象(通常是域对象):AspectJ是这种情况下的最佳选择。然而,我们的经验是,Spring AOP为企业适用于AOP的Java应用程序中的大多数问题提供了极好的解决方案。

Spring AOP将永远不会争取与AspectJ竞争,提供全面的AOP解决方案。我们认为,基于代理的框架,如Spring AOP和诸如AspectJ等全面的框架都是有价值的,而且它们是互补的,而不是竞争。 Spring将Spring AOP和IoC与AspectJ无缝集成,使AOP的所有使用都能够在一致的基于Spring的应用程序架构中得到满足。这种集成不会影响Spring AOP APIAOP Alliance APISpring AOP保持向后兼容。有关Spring AOP API的讨论,请参阅以下章节。

Spring框架的核心原则之一是非侵略性;这是您不应该被迫将特定于框架的类和接口引入您的业务/域模型的想法。然而,在某些地方,Spring Framework可以让您选择将特定于Spring Framework的依赖关系引入到代码库中:给予这些选项的理由是因为在某些情况下,读取或编写一些特定的功能如此。 Spring框架(几乎)总是为您提供选择:您可以自由地做出明智的决定,哪个选项最适合您的特定用例或场景。 
与本章相关的一个这样的选择是哪个AOP框架(以及哪种AOP风格)可供选择。您可以选择AspectJ和/或Spring AOP,还可以选择@AspectJ注解式方法或Spring XML配置样式方法。本章选择引入@AspectJ风格方法的事实不应该被视为表明Spring团队赞成使用Spring XML配置风格的@AspectJ注解式方法。 
请参见第11.4节“选择要使用的AOP声明样式”,以更完整地讨论每种风格的方式和位置。

11.1.3 AOP代理

Spring AOP默认使用用于AOP代理的标准JDK动态代理。 这使得任何接口(或一组接口)都可以被代理。

Spring AOP也可以使用CGLIB代理。 这对于代理类而不是接口是必需的。 默认情况下,如果业务对象不实现接口,则使用CGLIB。 因为编程到接口而不是类是好的做法; 商务课程通常会实现一个或多个业务接口。 有可能强制使用CGLIB(在希望罕见的情况下),您需要建议在接口上未声明的方法,或者需要将代理对象传递给方法作为具体类型。

了解Spring AOP是基于代理的事实很重要。 请参阅第11.6.1节“了解AOP代理”,以便对本实施细节的具体实际情况进行详细的检查。

你可能感兴趣的:(Part III. 核心技术-11. Spring面向切面编程-11.1 介绍)