本文主要介绍AOP思想,而不是Spring,Spring在本文只作为理解AOP的工具和例子,因此也不打算介绍Spring的Aspect、Join point、Advice、AOP proxy等概念,那样初学者会很难理解,若是你懂了AOP的思想,那么Spring的AOP,仍是AspectJ都容易理解了。html
Spring如此流行,当我第一次接触Spring的时候,到网上看了一些文章,都讲得神乎其乎,最后我篇也没看懂,我当时就是认为这个东西必定很高深,因而我就遇到作WEB开发的人就会打听一下。获得最多的一个回答就是“Spring是一个框架”,而后我就会问框架是什么,但都没有一种说法不让我感受玄乎乎的,同时也没有听懂,因而,我更感受Spring很神了,这可能叫作朦胧美。还有一种说法就是“Spring两个首要的特性就是AOP和IoC”,这种说法让我感受Spring简直神的飞上天了,我都不敢接着问了,再问可能想上天去找Spring了,后来我就怀疑这玩意儿真有那么高深吗,强列的好奇心让我实在hold,决定必定要试一下这个神器,因而就看了一些Step By Step的文章,本身写了一个HelloWorld,发现这AOP确实是一个比较新颖的思想,也算是打破了常规,是从不一样方面思考问题。不过没有那些童鞋说得那么神。java
本文旨在帮助尚未理解AOP的童鞋看透弄懂AOP,也欢迎高手批评指正。spring
先说一个Spring是什么吧,你们都是它是一个框架,但框架这个词对新手有点抽象,以至于越解释越模糊,不过它确实是个框架的,但那是从功能的角度来定义的,从本质意义上来说,Spring是一个库,一个Java库,因此我我的以为应该这样回答Spring是什么:Spring是一个库,它的功能是提供了一个软件框架,这个框架目的是使软件之间的逻辑更加清晰,配置更灵活,实现这个目的的手段使用AOP和IoC,而AOP和IoC是一种思想,是一种什么样的思想呢,等下细说,先说AOP在Java里是利用反射机制实现(你也能够认为是动态代理,不过动态代理也是反射机制实现的,因此仍是先不要管动态代理,咱们这里化繁为简,不让它干扰我们对AOP的理解),如何使用AOP呢,很简单滴,等下介绍。框架
下面先说AOP是什么样的思想,咱们一步一步慢慢来,先看一下传统程序的流程,好比银行系统会有一个取款流程ide
咱们能够把方框里的流程合为一个,另外系统还会有一个查询余额流程,咱们先把这两个流程放到一块儿:函数
有没有发现,这个二者有一个相同的验证流程,咱们先把它们圈起来再说下一步:工具
有没有想过能够把这个验证用户的代码是提取出来,不放到主流程里去呢,这就是AOP的做用了,有了AOP,你写代码时不要把这个验证用户步骤写进去,即彻底不考虑验证用户,你写完以后,在另我一个地方,写好验证用户的代码,而后告诉Spring你要把这段代码加到哪几个地方,Spring就会帮你加过去,而不要你本身Copy过去,这里仍是两个地方,若是你有多个控制流呢,这个写代码的方法能够大大减小你的时间,不过AOP的目的不是这样,这只是一个“反作用”,真正目的是,你写代码的时候,事先只需考虑主流程,而不用考虑那些不重要的流程,懂C的都知道,良好的风格要求在函数起始处验证参数,若是在C上能够用AOP,就能够先无论校验参数的问题,过后使用AOP就能够隔山打牛的给全部函数一次性加入校验代码,而你只须要写一次校验代码。不知道C的不要紧,举一个通用的例子,常常在debug的时候要打log吧,你也能够写好主要代码以后,把打log的代码写到另外一个单独的地方,而后命令AOP把你的代码加过去,注意AOP不会把代码加到源文件里,可是它会正确的影响最终的机器代码。ui
如今大概明白了AOP了吗,咱们来理一下头绪,上面那个方框像不像个平面,你能够把它当块板子,这块板子插入一些控制流程,这块板子就能够当成是AOP中的一个切面。因此AOP的本质是在一系列纵向的控制流程中,把那些相同的子流程提取成一个横向的面,这句话应该好理解吧,咱们把纵向流程画成一条直线,然把相同的部分以绿色突出,以下图左,而AOP至关于把相同的地方连一条横线,以下图右,这个图没画好,你们明白意思就行。spa
这个验证用户这个子流程就成了一个条线,也能够理解成一个切面,aspect的意思我认为是方面,你用什么实物去类比,只要你能理解均可以。这里的切面只插了两三个流程,若是其它流程也须要这个子流程,也能够插到其它地方去。.net
讲了这么多,那到AOP该如何使用呢?咱们要写一个HelloWorld吗,我看仍是算了,关于这种类型的文章,网上已经泛滥成灾,我再写也不必定比人家写得好,因此,我会在下面贴几个我认为写得不错的文章连接,但我在这里先介绍一下Spring如何实现AOP的吧。其实也不难理解,Spring的实现是基于函数(或叫方法)的,就是说,你写好了一个函数后,你还能够在不更改原来的代码状况,经过Spring在函数前或函数后动态的加入新的代码。好比你原来的代是这样的:
void foo() { System.out.println("in foo()"); }
而后你想在函数执行前(当成也能够加到执行后,或先后都加,原理是同样)加一句:
System.out.println("before execute foo()");
你也能够多加几句,经过Spring,你能够把这些代码动态的加到函数前面,而不用改变原来的代码。从而会获得与如下等效的执行码:
void foo() { System.out.println("before execute foo()"); System.out.pringln("in foo()"); }
我这样一说你可能更想亲手试试了,能够看看如下这篇文章,写得很好,咱们在此也感谢其做者的辛勤付出。
参考资料:
Spring AOP Guide: http://docs.spring.io/spring/docs/2.5.4/reference/aop.html