什么是AOP

Spring 是一个轻量级的IOC和AOP的框架,spring的两大核心就是IOC和AOP,IOC我之前写有,那什么是AOP呢?首先先看一下百度的定义。

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

面向切面编程

AOP,面向切面编程,这又是一种新的思想。一开始我们接触的是面向过程,比如c语言。然后是面向对象编程oop,一系列的面向对象语言,比如Java。学到后面就发现,面向对象也不能满足人们了,就出现了面向接口编程,但人总是懒得,这又出现了面向切面编程。面向切面顾名思义,把一个程序一刀切就出现了切面。怎么理解呢。就比如我们得业务,实现增删改查,一开始的我们是这样的。

这时候人们想增加一个功能,比如日志,就会变成这样

人们会发现这样会重复写了一段代码,当很多业务方法都需要加上日志这个功能的时候,就会多写很多的代码,为了简便,人们就想到了

增加一个类来实现日志就好了,就比如这样

但是每一个方法都要加多一段代码来调用日志的方法,这样也是很麻烦的,如果要有很多很多的方法,一个一个的加不仅会破环原方法的代码,还会很繁琐。

所以出现了我们面向切面开发的AOP。

这样大概就能理解什么是面向切面编程了吧。我们为了实现功能的操作,都可以理解为一条直线,从中切一刀,插入一个功能,该功能还能切入其他的方法,就这样便减少了代码的重复性,也减少了耦合。

AOP的术语

通知(Advice)

通知可以理解为你需要实现个功能,就比如上述例子的日志功能。

连接点(JoinPoint)

连接点就是你可以你可以使用通知功能的地方,就比如增加操作的前后都是可以增加日志功能的,方法前后都是连接点。

切入点(Pointcut)

切入点就很好理解了吧,上述的日志功能横穿两个方法,交点就是这个通知的切入点,这个交点也是连接点。其实切入点就是连接点,连接点是你能够使用通知的地方,这些地方会有很多,但你不会所有都用,有些地方你就不会去使用通知的功能,你用通知的连接点才是切入点。

切面(Aspect)

切面其实就是通知和切入点的结合,这两者结合就把一个方法切出一个面,所以叫切面。

引入(introduction)

引入的意思就是把切面用到目标里。比如查询需要引入日志这个通知,就是把查询这个功能也切一刀。

目标(target)

目标其实就是指需要添加通知的对象,就是刚刚所说的那条线。

代理(proxy)

看到这其实就发现AOP与之前所说的动态代理很像,整个的AOP实现其实都是通过代理来实现的,没了解过动态代理的可以去参考一下我之前的文章

织入(weaving)

把切面应用到目标对象来创建新的代理对象的过程。有3种方式,spring采用的是运行时。

AOP的实现原理

刚刚也说到了,AOP其实就是通过动态代理来实现的。spring用代理类包裹切面,把它们织入到Bean中,从而代理类代替原有的类拦截了方法的调用,拦截了方法的调用然后改代理类又实现了一些附带的功能,然后再把方法调用转发给Bean,从而实现了AOP。

怎么拦截就是代理的问题了。动态代理分为两种,一个是基于接口的动态代理,就是JDK的动态代理,另一个便是基于类的代理,就是使用cglib的动态代理。

  1. 基于接口的动态代理
    目标类和代理类都实现了同一接口,但不同的是代理类能会实现一些附带的功能,目标类只是代理类的一部分,虽然最后都是目标类完成接口的功能,但代理类不同于接口的方法就可以插入到目标类实现接口方法的前后,这就实现了AOP。就像是代理类里有两兄弟,实现了接口的那些方法就是哥哥,而实现了不同于接口方法的其他功能就是弟弟,当人们想要完成接口的方法的时候,弟弟虽然办不到,但是他招待了你(就是意义上的拦截),你以为他是能实现接口的哥哥,便把任务给了他,弟弟答应了又顺带收了你的钱(即附加的功能,比如日志),然后弟弟知道自己不能做这个任务,便让哥哥实现,这就是JDK的动态代理实现AOP的方式。
  2. 基于类的动态代理
    基于类那就更加好理解了。目标类就像是父亲,而继承了目标类的代理类就是儿子。人们都找儿子去实现接口的功能,但是儿子在完成接口的任务之前或者之后都会做一些其他的事(即附加的功能,比如日志),所以这就是cglib的动态代理实现AOP的方式。

参考文章

这两篇还是很好理解的,此文就是借鉴两文然后加上我自己的理解写成的。