SpringFramework

Spring AOP (一) 简介

2019-05-05  本文已影响55人  蓝笔头

面向切面编程(Aspect Oriented Programming, AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP)。OOP 中模块化的关键单元是类,而在 AOP 中,模块化单元是切面。

AOP 旨在从业务逻辑中分离出来通用逻辑,切面实现了跨越多种类型和对象的关注点(例如事务管理、日志记录、权限控制)的模块化。(这些在 AOP 文献中通常被称为 “横切” 问题。)

切面织入的三种方法:

AOP 的概念和术语

让我们首先定义一些重要的 AOP 概念和术语。这些术语不是特定于Spring的。不幸的是,AOP 术语不是特别直观。但是,如果 Spring 使用自己的术语,那将更加令人困惑。

Spring AOP 包括以下类型的通知:

环绕通知是最通用的通知。由于 Spring AOP(如 AspectJ)提供了全方位的通知类型,因此我们建议您使用可以实现所需行为的影响范围最小的通知类型。

例如,如果您只需要使用方法的返回值更新缓存,那么最好实现后置通知而不是环绕通知,尽管环绕通知可以完成同样的事情。

使用最具体的建议类型可以提供更简单的编程模型,减少错误的可能性。例如,您不需要在用于环绕通知的 JoinPoint 上调用 proceed() 方法,因此,您不会忘记调用它。

所有通知参数都是静态类型的,因此您可以使用相应类型的通知参数(例如,方法执行的返回值的类型)而不是 Object 数组。

由切入点匹配的连接点的概念是 AOP 的关键,它将其与仅提供拦截的旧技术区分开来。切入点使得通知可以独立于面向对象的层次结构进行定向。例如,您可以将一个提供声明性事务管理的通知应用于跨多个对象的一组方法(例如服务层中的所有业务操作)。

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 实现的重要区别。

AOP 代理

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

Spring AOP 也可以使用 CGLIB 代理。这是代理类而不是接口所必需的。默认情况下,如果业务对象未实现接口,则使用 CGLIB。

由于优化的做法是编程接口而不是类,业务类通常实现一个或多个业务接口。可以强制使用 CGLIB,在那些需要建议未在接口上声明的方法或需要将代理对象作为具体类型传递给方法的情况下(希望很少见)。

掌握 Spring AOP 是基于代理的这一事实非常重要

代理机制

Spring AOP 使用 JDK 动态代理或 CGLIB 为给定目标对象创建代理。JDK 动态代理内置在 JDK 中,而 CGLIB 是一个常见的开源库。

如果要代理的目标对象实现至少一个接口,则使用 JDK 动态代理。目标类型实现的所有接口都是代理的。如果目标对象未实现任何接口,则会创建 CGLIB 代理。

如果要强制使用 CGLIB 代理(例如,代理为目标对象定义的每个方法,而不仅仅是那些由其接口实现的方法),您可以这样做。但是,您应该考虑以下问题:

要强制使用 CGLIB 代理,请将元素 proxy-target-class 属性的值设置<aop:config>true,如下所示:

<aop:config proxy-target-class="true">
    <!-- other beans defined here... -->
</aop:config>

要在使用 @AspectJ 自动代理支持时强制 CGLIB 代理,请将元素的 proxy-target-class 属性设置 <aop:aspectj-autoproxy>true,如下所示:

<aop:aspectj-autoproxy proxy-target-class="true"/>

参考文献

(正文完)

喜欢本文的朋友们,欢迎关注微信公众号【程序员小课堂】,阅读更多精彩内容!


程序员小课堂.jpg
上一篇下一篇

猜你喜欢

热点阅读