面向切面编程AOP

一、什么是AOP?

AOP(Aspect Oriented Programming)面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。是面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被称为“切面”(Aspect)

简单的说它就是把程序中重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强

二、名词解释

  • 横切关注点:与我们业务逻辑无关但需要关注的部分,如日志、事务、安全、缓存等

  • 切面(Aspect):横切关注点被模块化的特殊对象,即它是一个类(日志类log)

  • 通知(Advice):切面必须完成的工作。即它是类的一个方法(Log中的方法)

    • 前置通知(before) 目标方法被调用之前调用通知功能
    • 后置通知(after) 在目标方法完成之后调用通知此时不会关心方法输出什么
    • 后置返回通知(after returing) 目标方法成功执行后调用通知
    • 异常通知(after throwing) 在目标方法抛出异常后调用通知
    • 环绕通知(around) 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义行为
  • 目标(Target):被通知对象(接口)

  • 代理(Proxy):想目标对象应用通知后创建的对象(生成的代理类)

  • 切入点(PointCut):切面通知执行的“地点”的定义

  • 连接点(JointPoint):与切入点匹配的执行点

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

三、知乎大佬的理解

举个栗子,我们需要在两个类中每个方法中做日志。按照面向对象的设计思想,就需要在两个类的方法中都加入日志的操作,或许他们是完全相同的,但面向对象的设计让类与类之间无法联系,不能将重复的代码统一起来

或许你会想到可以将这段代码写在一个类的独立方法里,然后在这两个类中调用。但这样会使得这两个独立的类产生耦合,它的改变会影响这两个类

那么有什么办法能让我们需要时随意加入代码呢?

这种在运行时,动态将代码切入到类的指定方法、指定位置上的编程思想就是面向切面编程。

一般而言,我们管切入到类的指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码抽取到一个切片中,等需要时再切入对象中,从而改变其原有的行为。

四、作用与优势

1. 作用

在程序运行期间,不修改源代码对已有的方法进行增强

2. 优势

-   减少重复代码
-   提高开发效率
-   维护方便

五、实现AOP的方式

主要有两大类:

  • 采用动态代理技术,利用拦截方法的方式,对该方法进行装饰,以取代原有对象行为的执行
  • 采用静态织入的方式,引入特定的语法创建‘切面’,从而使得编译器可以在编译期间织入有关‘切面’的代码

六、使用Spring实现Aop

使用AOP织入,需要导入一个依赖包

1
2
3
4
5
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>

方式一、使用原生Spring接口

通过Spring执行AOP切入

方式二、自定义类来实现

把类标记为切面

方式三、使用注解实现

标注这个类是一个切面

七、JDK和CGLB动态代理的区别

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

1.JDK动态代理

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

2.CGLIB动态代理

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

请我喝杯咖啡吧~

支付宝
微信