Spring面向切面编程(AOP)
什么是AOP
- OOP(Object-Oriented Programming)面向对象编程,允许开发者定义纵向的关系,但并不适用于定向横向的关系。定义横向会导致大量的代码重复,不利于各个模块的复用
- AOP(Aspect-Oriented Programming),一般称为面向切面编程,作为面向对象的一种补充。将那些与业务无关,却对多个对象产生影响的公共行为和逻辑,抽取封装成一个可重用的模块,这个模块被命名为“切面”(Aspect),减少重复代码,降低模块间的耦合性,同时提高代码的可维护性。常用于权限认证、日志、事务处理等功能。
AOP的主要实现方式
- AOP的主要实现方式是代理模式。AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ,动态代理的代表为Spring AOP。
- (1)AspectJ是静态代理的增强。所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的就是增强后的AOP对象
- (2)Spring AOP使用的是动态代理,所谓的动态代理就是说AOP框架不会去修改Java字节码。而是在每次运行的时候再内存中临时生成一个AOP对象,这个AOP对象包含了目标对象的所有方法,并在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP 实现动态代理的方式
Spring AOP主要使用了JDK动态代理和CGLIB动态代理:
- JDK动态代理只提供接口的动态代理,不支持类的代理。核心
Invocationhandler接口和Proxy类,Invocationhandler通过invoke()方法来反射调用目标类中的代码,动态的将横切逻辑代码和业务编制在一起;接着,Proxy利用Invocationhandler动态的创建一个符合某一接口的实例,生成目标类的代理对象。 - CGLIB是用来提供类的动态代理。如果代理类没有实现
Invocationhandler接口,那么Spring AOP就会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,覆盖其中的某些方法并添加增强方法,从而实现AOP增强。CGLIB是通过集成的方式做动态代理的,如果一个类被final声明了,那么这个类无法使用CGLIB做动态代理
Spring AOP 相关的术语
- (1)切面(Aspect):切面是通知和切点的结合。通知和切点共同定义了切面的全部内容。在Spring AOP中,切面可以使用通用类(基于模式的风格),或者在普通类中使用@Aspect注解来实现
- (2)连接点(Join point):指方法,在SpringAOP中,一个连接点总是代表一个方法的执行。类中的那些方法可以被增强,这些方法就称为连接点。
- (3)通知(Advice):实际增强的部分逻辑称之为通知(增强)
- 前置通知(Before):在目标方法被调用之前调用通知功能。
- 后置通知(After):在目标方法完成之后通知调用,此时不会关心方法输出的是什么。
- 返回通知(After-Running):在目标方法成功执行之后调用通知
- 异常通知(After-throwing):在目标方法抛出异常之后调用通知
- 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
- (4)切入点(PointCut):切点定义会匹配要通知的一个或者多个连接点。我们通常使用明确的类和方法的名称。或是利用正则表达式所匹配的类和方法名称来指定这些切点。
- (5)引入(Introduction):引入允许我们向现有的类添加新的属性和方法
- (6)目标对象(Target Object):被一个或多个切面所通知的对象,它通常是代理对象。也有人把他叫做被通知的对象。
- (7)织入(Weaving):织入就是把切面应用到目标对象并创建代理对象的过程。在目标对象的生命周期有多个点可以进行织入。
-
编译期:切面在编译期时被织入,AspectJ就是已这种方式织入的
-
类加载期:切面目标在被加载进JVM的时候被织入。需要特殊的类加载器,它可以在目标类被引入应用之前增强目标类的字节码。AspectJ5加载时就支持这种织入方式。
-
运行期:切面在应用运行的某个时刻被织入。在织入切面的时候,AOP会动态的为目标对象生成一个代理对象。
-