舌尖上的AOP

来源:互联网 发布:赤瞳 喜欢 知乎 编辑:程序博客网 时间:2024/04/27 22:47


AOP是目前一个比较热门的话题AOPAspect Oriented Programming的缩写译作“面向切面编程”AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。

 

AOP到底是什么?

面向切面编程切面这个东西我的理解更像是流水线中的一个环节不知道有没有过这种感受我们写好的代码突然需要加入一个鉴别用户是否登录再决定是否要给用户提供服务,那么应该怎么做?我们去到每个代码块,在每个方法的第一行加入一行取session查看是否登录的判断语句。

 

这个时候问题就来了,这种登录验证的代码重复出现在了多个代码中,与实现了业务逻辑的方法体产生了耦合,那么我们改用另一种方法,我们把这个代码提取出来写成一个函数,然后把代码原来的位置改成这个方法的调用,不就解决了吗?

 

然而并不行因为这样仍然存在耦合只不过看起来清爽了很多但是下一个新的业务也许又要调用一遍这个方法。而问题就在这里,有些系统级的逻辑,比如日志、用户身份、事务管理等这种每个类都需要依赖的办法,会导致我们的方法越来越臃肿,而写一个业务逻辑代码反而会产生很多与业务无关的代码在其中。

 

AOP就是解决这个问题而存在的。如果我们把M作为我们的业务,abc作为上述的日志、用户身份、事务管理,那么传统的写法可能就是abcM,而面向切面编程就是让我们这么做

abc|M,我们把M单独切出来,只写M,然后再写好abc,等到运行的时候,把abc再和M全部连在一起。

 

我们可以举一个比方上个Ioc我们用了保姆和我的例子,通过做饭来告诉大家什么叫Ioc,那么今天我们就还是用类似的办法让大家理解什么是AOP

 

AOP,一句话,就是:做自己喜欢的事。

 

传统OOP:小时候喜欢吃蛋白,不喜欢吃蛋黄,但是因为蛋黄的存在导致我不喜欢吃鸡蛋。另一方面,每次吃鸡蛋还要剥壳,还特别麻烦,因此每次不管鸡蛋还是鸭蛋,看到那壳和里面干巴巴的蛋黄就一点兴趣都没有。

 

改良版AOP:小时候喜欢吃蛋白(Target目标,做爱做的事),每次桌子上都会有很多鸭蛋白、鸡蛋白(Aspect方面),而吃之前(Advice通知)的剥壳(连接点),和蛋黄都没有了,后来长大了,才知道每次妈妈煮完鸡蛋都会帮我把壳和蛋黄拿掉(Introduction引入),然后看着我吃完喜欢吃的蛋白。

 

可以看出来AOP做的就是让我们做自己喜欢的事情,不管是什么蛋,都会把壳去掉,让我不需要关心这些影响我吃鸡蛋的事情,而我只需要知道怎么吃鸡蛋就好了,这整个一件事情发生是完整的,包含剥壳+ 吃的动作,但是在我的眼里,只有吃这一个过程,那么这个吃就是完整过程中的一个切面,而我只用关注着一个切面就好了,这就是面向切面编程,也许完成的一次过程包含abcdefgM但是abcdefg都不归我管我只喜欢做M,那么我就只做M这件事,而徐志远喜欢做N,那么他就只做N这件事,而每次需要叫我做事,都会先经历abcdefM,而叫徐志远做事,则是abcdefgN,但是在我们两个的眼中只有MN

 

 

Spring——AOP

SpringAOP的实现,接触的比较多的便是所谓的Interceptor(拦截器)

 

拦截器需要实现HandlerInterceptor这是一个方法拦截器有三个需要实现的方法

boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;

这三个方法根据名字就能看出来是对应着一次调用的三个阶段

分别是调用handlerhandler执行后调用完成

这就是一种AOP实现,在我们的控制器中,我们实际上写的是一个业务的逻辑,可是,在拦截器里,定义了这三个方法,那么实际运行的时候:

preHandler

controller

postHandler

afterCompletion

是这样运行的拦截器引入到我们所谓的控制器(切面)的不同阶段,当控制器需要被调用的时候,就必须要经过preHandler这个阶段(剥壳),那么controller做完爱做的事情(吃蛋白),又要调用postHandlerafterCompletion(丢掉),这就是面向切面编程。Controller不需要设计系统逻辑,只需要去完成自己要做的业务逻辑,而一切包括用户身份、事务管理等交由拦截器来做,就是一种AOP的思想。