Spring面向切面编程(AOP)

定义:

AOP(Aspect-Oriented Programming),面向切面编程,是面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect)。

OOP(Object-Oriented Programming)面向对象编程,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。

作用:

减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。

Spring AOP and AspectJ AOP的区别:

AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。

  • AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。

  • Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

    Spring AOP中的动态代理主要有两种方式:

    1. JDK动态代理

      只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。

    2. CGLIB动态代理

      如果代理类没有实现InvocationHandler接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。

CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

静态代理与动态代理区别在于生成AOP代理对象的时机不同:

相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理。

Spring 中的代理:

将 Advice 应用于目标对象后创建的对象称为代理。Advice + Target Object = Proxy

名词解释:
  1. 切面(Aspect)

    切面是通知和切点的结合。通知和切点共同定义了切面的全部内容。 在Spring AOP中,切面可以使用通用类(基于模式的风格) 或者在普通类中以 @AspectJ 注解来实现。

  2. 连接点(Join point)

    指方法,在Spring AOP中,一个连接点总是代表一个方法的执行。 应用可能有数以千计的时机应用通知。这些时机被称为连接点。连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

  3. 通知(Advice)

    在AOP术语中,切面的工作被称为通知。

    类型:

    • 前置通知(Before):在目标方法被调用之前调用advice,但无法阻止程序执行到连接点(除非advice执行的逻辑抛出异常)。使用@Before注解声明。

    • 后置通知(After (Finally)):在目标方法完成之后调用advice。该advice应该能够处理正常退出和抛出异常的情况。使用@After注解声明。

    • 返回通知(After-returning ):在目标方法成功执行之后调用advice(例如方法正常返回,并且没有抛出异常)。使用@AfterReturning注解声明。

    • 异常通知(After-throwing):在目标方法抛出异常后调用advice。使用@AfterThrowing注解声明。

    • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的代码逻辑。是最强大的一种advice。它甚至可以决定程序是否执行到连接点,或者通过返回自己的值或抛出异常”短路“目标方法,目标方法从而根本不会得到执行的机会。使用@Around注解声明。

  1. 切入点(Pointcut)

    切点的定义会匹配通知所要织入的一个或多个连接点。我们通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。

  2. 引入(Introduction)

    引入允许我们向现有类添加新方法或属性。

  3. 目标对象(Target Object)

    被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做被通知(adviced) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。

  4. 织入(Weaving)

    织入是把切面应用到目标对象并创建新的代理对象的过程。

    织入的时间点:

    • 编译期

      切面在目标类编译时被织入。AspectJ的织入编译器是以这种方式织入切面的。

    • 类加载期

      切面在目标类加载到JVM时被织入。需要特殊的类加载器,它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入就支持以这种方式织入切面。

    • 运行期

      切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面。

你可能感兴趣的:(Spring面向切面编程(AOP))