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 一样的注解,降低开发人员的理解成本。
术语
连接点(JoinPoint):具体的切入点
切面(Aspect):通知(Advice)和切点(PointCut)的集合,切点:一个或者多个位置,或者某一类位置,通知:对原功能(方法)进行增强
织入(Weaving):切面作用到目标代码中的方式,Spring 内置的 AOP 采用的是动态代理(jdk 动态代理和 cglib 动态代理)的方式来织入、还有 AspectJ 静态代理织入
引介(Introduction):对类进行增强,和通知(Advice)并列
目标对象(Target):一类要织入的对象
代理(Proxy):通过织入目标对象可生成的代理对象;并通过代理对象来调用目标对象的方法,达到织入的目的
Spring 中配置 @AspectJ,开启 AOP
XMl 方式:<aop:aspectj-autoproxy/>
注解方式:@EnableAspectJAutoProxy