Spring AOP

1,751 阅读5分钟

AOP是什么?

AOP这词听起来耳熟,然而能清晰把它说清楚应该是少数。学习它,从历史的进程中看看AOP是何时为何出现,这样认识会比较立体。

名称 含义 应用
POP Process oriented programming C
OOP Object oriented programming) Java
COP Component oriented programming ReactiveJS
AOP Aspect oriented programming AspectJ,Spring
SOP service oriented programming Microservices

从C开始,大家是面向过程编程,高级语言Java出现,提出OOP的编程法则,OOP在复用的不足催生了AOP。与此同时JS风靡,ReactiveJS提倡的面向组件封装COP思想被广泛接受。后端业务的高度复杂化带来的解耦和自治诉求也使SOP越来越流行。

所以和OOP一样,AOP也是一种编程范式,通过添加切面点,在不改动已有核心逻辑代码的前提下,添加功能或更改代码流程。

提出

Xerox PARC的Gregor Kiczales及其同事提出了AOP概念和相关术语,并以此开发了AspectJ 和AspectWerkz。企业级应用Jboss 4.0 就是完全采用 AOP 的思想来设计的 EJB 容器,它通过了 J2EE 的认证,在工业化应用中被证明表现优秀。Spring 2.0后使用了与AspectJ一样的注解,但没有使用 AspectJ 的编译器,底层是Java库标准的动态代理技术的实现,所以不需要额外依赖一个 AspectJ 的编译器。

术语

  • Cross-cutting concerns:跨领域的问题

尽管OO模型中的大多数类都执行单个特定功能,但它们通常与其他类共享共同的次要要求。例如,我们可能希望在线程进入或退出方法时向数据访问层中的类添加日志记录,也可以向UI层中的类添加日志记录。还有些可能与安全性有关,例如访问控制信息流控制。尽管每个类具有非常不同的主要功能,但执行辅助功能所需的代码通常是相同的。

  • Advice:通知建议

这是你要应用于现有模型的附加代码。比如在线程进入或退出方法时应用的日志记录代码。

  • Pointcut:切入点

这是应用程序中执行点的术语,需要应用交叉关注点。比如,当线程进入方法时达到切入点,并且当线程退出方法时达到另一个切入点。

  • Aspect:切面

切入点和建议的组合被称为方面。我们通过定义切入点并提供正确的建议,为应用程序添加日志记录方面。

AOP用来做什么?

如上面所提到的,我们可以将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非业务逻辑的方法中,进而在这些行为改变的时候不影响业务逻辑的代码。

从场景来说Android,iOS,Java Spring都用AOP的专业应用场景。它不是必须,但这些场景用AOP给系统带来的好处是显然易见的。我们学习AOP在Java Spring里的应用,喝水不忘挖井人,那我们先了解下AspectJ。

AspectJ

AspectJ的动机是发现那些使用OOP无法很好处理的问题。比如安全性是贯穿于系统所有模块间的问题,每个模块都需要应用安全机制才能保证整个系统的安全性,这里的安全策略的实施其实就是一个横切关注点,使用传统的编程解决此问题非常麻烦而且容易产生差错,这就正是AOP发挥作用的时候了。

传统的面向对象编程中,每个单元就是一个类,而类似于安全性这方面的问题,它们通常不能集中在一个类中处理因为它们横跨多个类,这就导致了代码无法复用,从而产生了大量代码冗余。

面向切面编程的出现正好能处理这种场景,AspectJ应运而生,并定义了AOP,它向Java中加入了连接点(Join Point)和少许新结构:切点(pointcut)、通知(Advice)、类型间声明(Inter-type declaration)和切面(Aspect)。切点和通知动态地影响程序流程,类型间声明则是静态的影响程序的类等级结构,而切面则是对所有这些新结构的封装。

Spring AOP

Spring AOP 与AspectJ 的初衷一致,都是为了统一处理横切业务,但与AspectJ不同的是,Spring AOP 并不提供完整的AOP功能(即使它完全可以实现),Spring AOP 更注重的是与Spring IOC容器的结合,并结合该优势来解决横切业务的问题。

同时,Spring注意到AspectJ在AOP的实现方式上依赖于特殊编译器(ajc编译器),处于应用成本考虑,Spring选择规避这点,采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这与AspectJ(静态织入)有根本的区别。在AspectJ 1.5后提出@Aspect形式的注解风格。Spring也非常快地跟进了这种方式,所以Spring 2.0后便使用了与AspectJ一样的注解,降低开发人员的理解成本。

通配符

  • .. :匹配方法定义中的任意数量的参数,此外还匹配类定义中的任意数量包

  • + :匹配给定类的任意子类

  • * :匹配任意数量的字符

实现原理

上面提到Spring的AOP是通过动态代理技术实现的,具体来说如果一个有实现接口那就通过JDK内置的工具类反射生成代理类,如果没有实现接口那需要依赖一个CGLIB动态库,通过继承来动态生成一个代理类。

v2-e777957e808c92fefcbcbec3945a2f91_hd

Demo

思考问题

1,私有方法能否被切?

2,spring aop实现原理?

3,为什么要有两种实现?

参考

Aspect oriented programming

关于 Spring AOP

(完)

@子路宇, 本文版权属于再惠研发团队,欢迎转载,转载请保留出处。