Spring——AOP
SpringAOP基础
AOP简介:
AOP是Aspect Oriented Programing的简称,翻译为“面向切面编程”。它适用于具有横切逻辑的应用场合,如性能检测,访问控制,事务管理及日志记录。
在开发中,在业务层有时会涉及到事务的处理和性能检测,例如粗体是事务有关的代码,这些代码和业务逻辑混合在了同一个方法中。
很多时候这些代码和业务逻辑没法分离,并且这些代码是重复代码,AOP通过横向抽取机制为这类代码提供解决方案。AOP将这些分散在各个业务逻辑的代码中的相同代码通过横向切割的方式抽取到一个独立模块中,让业务逻辑类不会和其他内容混合在一起。
AOP术语:
1、连接点(JoinPoint)
特定点是程序执行的某个特定位置,如类初始化前、类初始化后、类的某个方法调用前/后、方法抛出异常后。一个类或一段程序代码拥有一些具有边界性质的特定点,这些点被称为“连接点”。Spring仅支持方法的连接点,即仅能在方法调用前、方法调用后、方法抛出异常时及方法调用前后这些程序执行点织入增强。
连接点由两个信息确定:一是方法表示的程序执行点;二是用相对位置表示的方位。如对于在run()方法执行前的连接点,执行点位run(),方位为该方法执行前。Spring使用切点对执行点进行定位,而方位则在增强类型中定义。
2、切点(Pointcut)
每个程序类都拥有多个连接点,如一个拥有两个方法的类,这两个方法都是连接点。在众多连接点中,如何定位某些连接点呢?AOP通过“切点”定位特定的连接点。书上原文:借助数据库查询的概念来理解切点和连接点的关系再适合不过了;连接点相当于数据库中的记录,而切点相当于查询条件。切点和连接点不是一对一的关系,一个切点可以匹配多个连接点。 可理解为类中的某个方法。
连接点是方法执行前、执行后等包括方位信息的具体程序执行点,而切点只定位到某个方法上,如果希望定位到具体的特殊点上(如方法执行前、执行后),还需要提供方位信息。
3、增强(Advice)
增强是织入目标类连接点上的一段程序代码。在Spring中,增强除用于描述一段程序代码外,还拥有另一个和连接点相关的信息,这便是执行点的方位。结合执行点的方位信息和切点信息,就可以找到特定的连接。
正是由于增强既包含用于添加到目标连接点上的一段执行逻辑,又包含用于定位连接点的方位信息,所以Spring提供的增强接口都是带方位名的,如BeforeAdvice、AfterReturningAdvice等。所以只有结合切点和增强,才能确定特定的连接点并实施增强逻辑。
4、目标对象(Target)
增强逻辑的织入目标类。如果没有AOP,目标类需要自己实现所有逻辑,例如事务开启->业务逻辑->提交事务。在AOP的帮助下,目标类秩序实现那些非横切逻辑的程序逻辑(业务逻辑),而事务管理、性能监视等横切逻辑可以通过AOP动态织入到特定的连接点上。
5、引介(Introduction)
引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,也可以动态地为该业务添加接口的实现逻辑,让业务类成为这个接口的实现类。
6、织入(Weaving)
织入是将增强添加到目标类的具体链接点上的过程。根据不同的实现技术,AOP有3种织入方式:
(1)编译期织入,这要求使用特殊的Java编译器。
(2)类装载期织入、这要求使用特殊的类装载器。
(3)动态代理织入、在运行期为目标类添加增强生成子类的方式。
Spring采用动态代理织入、而AspectJ采用编译期织入和类装载期织入。
7、代理(Proxy)
一个类被AOP织入增强后,就产生了一个结果类,该类结合了原类和增强逻辑的代理类。
8、切面(Aspect)
切面由切点和增强组成,它即包括横切逻辑的定义(需要织入的逻辑),也包括连接点的定义(织入位置的定位)。Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入切面所指定的连接点中。
AOP工具的设计目标是把横切的问题(如性能监视、事务管理)模块化。位于AOP工具核心的是连接点模型,它提供了一种机制,可以定位到需要在哪里发生横切。
Spring AOP使用的代理机制:
Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理。之所以需要两种代理机制,很大程度是因为JDK本身只提供接口的代理,而不支持类的代理。
AOP所做的内容通过动态代理技术也可以实现,Spring AOP的底层也是通过这种技术实现的。然而,通过动态代理实现有几个需要改进的地方:
1、目标类的所有方法都添加了横切逻辑,我们可能只希望对特定方法添加横切逻辑。
2、通过硬编码的方式制定了织入横切逻辑的织入点,即在目标类业务方法的开始和结束前织入代码。
3、手工编写代理实例的创建过程,在为不同类创建代理时,需要分别编写相应的创建代码,无法做到通用。
以上3个问题在AOP中占有重要的地位,因为Spring AOP的主要工作就是围绕以上3点展开的:Spring AOP通过Pointcut(切点)指定在哪些类的哪些方法织入横切逻辑,通过Advice(增强)描述横切逻辑和方法的具体织入点(方法前、方法后、方法两端等)。此外,Spring通过Advisor(切面)将Pointcut和Advice组装起来。有了Advisor的信息,Spring就可以利用JDK和CGLib动态代理技术采用统一的方式为目标Bean创建织入的代理对象了。
CGLib和JDK动态代理的选择:
CGLib所创建的动态代理对象的性能比JDK所创建的动态代理对象的性能提高不少。但是CGLib在创建代理对象时所花费的时间却比JDK动态代理多。对于singleton的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,所以比较适合采用CGLib动态代理技术,反之则适合采用JDK动态代理技术。
定义切面
Spring定义切面的方式有4种,他们的本质都是相同的,都是定义切点和增强,只是在表示形式上有所不同。
小结:
AOP是OOP的延伸,它为程序开发提供了一个崭新的思考角度,可以将重复性的横切逻辑抽取到统一的模块中通过OOP的纵向抽象和AOP的横向抽取,程序才可以真正解决重复性代码问题。