AOP
AOP是目前一个比较热门的话题,AOP为Aspect 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,但是在我们两个的眼中只有M和N
Spring——AOP
Spring中AOP的实现,接触的比较多的便是所谓的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;
这三个方法,根据名字就能看出来,是对应着一次调用的三个阶段。
分别是:调用handler前,handler执行后,调用完成
这就是一种AOP实现,在我们的控制器中,我们实际上写的是一个业务的逻辑,可是,在拦截器里,定义了这三个方法,那么实际运行的时候:
preHandler
controller
postHandler
afterCompletion
是这样运行的,拦截器引入到我们所谓的控制器(切面)的不同阶段,当控制器需要被调用的时候,就必须要经过preHandler这个阶段(剥壳),那么controller做完爱做的事情(吃蛋白),又要调用postHandler和afterCompletion(丢掉),这就是面向切面编程。Controller不需要设计系统逻辑,只需要去完成自己要做的业务逻辑,而一切包括用户身份、事务管理等交由拦截器来做,就是一种AOP的思想。