快速了解Aop

转载自知乎:

作者:技能树IT修真院
链接:https://www.zhihu.com/question/24863332/answer/478673303
来源:知乎

刚开始看到面向切面编程的时候,就觉得好神奇。

切面?立体几何吗,有没有面向挂面编程?

脑袋里面很难有这种概念,想像不出来什么叫做切面。

这种类似的东西挺多,包括Pipe,Port,Stream之类的。

所以倒底应该怎么样正确理解他们呢?

“想要学会,先要忘记” -by 暗灭大人

先忘记这是什么概念,我们先看看看存在什么问题。

是的,按照修真院一直推荐的【上帝视角】,我们先不管AOP是什么,先关注于要解决的问题是什么。

这要从日志说起。

对于后端而言,解决问题的方法有三种。

1 断点调试。
2 查看日志。
3 重启。

前端用断点比较多,可以不夸张的说,大部分前端都可以通过回放操作的方式来完成系统的调试。

而对于后端的工程师兄弟而言,这个难度就要大很多了。

因为后端是要部署到远程服务器的,在服务器上,往往同时要处理很多很问题。

所以是绝对不能断点调试的,其实有远程断点功能。

在我年少无知的时候,很Happy的试了一下。。。

你们猜发生了什么事情?

所有的请求都被挂起了。

反正我是被吓到了。

在线远程调试?算了,就是测试环境我也不会想,自己的本地环境还是可以考虑一下的。

所以,后端有一个很重要的解决问题的方式,就是查看日志。

怎么查看日志呢?

从收到用户的请求开始,调用了什么方法,数据发生了哪些变化,经历了什么分支,全部写的清清楚楚(在线上的话会做很多简化,毕竟日志是很耗性能的)。

所以每一个后端工程师,在某种程度上去有福尔摩斯的潜质。

要通过蛛丝马迹,呸,日志打那么清楚了还蛛丝马迹,要通过神迹,把事情发生的顺序,一点一点的在脑袋里回放。

<noscript>![image](https://upload-images.jianshu.io/upload_images/19918407-45924e12fd0fed88.jpg?imageMogr2/auto-orient/strip%7
eView2/2/w/1240)

</noscript>

image

嗯。月光宝盒!

这就是日志的作用。

但除此之外内,日志还有一个很重要的作用,就是用来记录响应时间。

你们去饭店,一定见过一个沙漏吧?

<noscript>
image

</noscript>

image

用来干嘛的呢?

就是用来记时的啊。

如果沙漏流完了,在规定的时间之内,菜品还没上齐,就要免单。

有没有遇到过?

有没有偷偷把沙漏反过来?

emmmmmm,反正我是真没有。

沙漏就是一个端到端的计时器,对于服务端来说,就是一个端到端的响应时间,打开浏览器,打开F12,查看响应时间,就是同样的沙漏。

那么,我们看到的是这么一个沙漏,在饭店的后厨,是不是也应该有这种同样的沙漏,来确认每一个环节不出问题呢?

这就是关于性能的追求产生的需求,对程序员的专用术语来讲,就是我们要弄清楚,倒底可以分解成哪些阶段,每个阶段各自花费的时间是多少。

怎么统一一个方法的执行时间呢?

很简单,比如说切菜师傅,切菜师傅手里有一只笔,在接到一个单子之后,立刻看一下厨房里的时钟,在纸上记录下当前时间。

等菜切完之后,再记录一下结束时间。

结束时间减去开始时间,这就是他切菜用的时间,对不对?

以此类推,洗菜,切菜,炒菜,装盘,上桌等等几个环节都可以用同样的方式来处理时间的问题。

在编程语言上,就是用:

Long start=System.currentTimeMillis();

//process start
........
........
........
........
// process end
Long end =System.currentTimeMillis();

log.info("process use time is "+(end-start))

这就是想当于把后厨做饭的每一个环节都先标记时间,然后再记录结束时间。

最终我们知道了所有的环节处理时间。

完美~~~

可是后来发现有一个问题。

就是记录的时间太多了,而我们的最初要记录这些时间的目标是什么呢?

是为了找出响应缓慢的时间节点啊。那些正常的响应时间我不需要知道。

意思就是找异常。比如说,正常来讲,切一个黄瓜丝,3分钟,结果你用了15分钟,想把黄瓜切出花来,在每一根丝上都留下自己的名字。

<noscript>
image

</noscript>

image

那你每天切100根黄瓜(喂,那位漂亮的黄发女生不要捂脸害羞的笑啊,你想到哪里去了)

其中99根都是在3分钟之内切完的,我就不需要知道了啊。

只有一根你花了15分钟,我就需要花时间去调研一下了问题出在哪里了,是不是对这根黄瓜产生感情了。。。?

好了好了,不要多想了,我们就是想说明,我们的需求是这样的。

对方法的响应时间做一个判断,超过200MS,我们就打出来日志。没超过200MS,我就不打日志了。

这代表什么含义呢?

切菜的师父(假设就是少楠在切菜)仍然记录时间,切完之后再记录时间,然后判断一下这个时间是否超过了200MS(emmmm切菜肯定超过),如果超过了。就在纸上写一下,这根黄瓜用了多长时间,如果没超过,就不写了。

这样后厨主管半导来检查的时候,就可以直接看这些异常的时间就好了。

那换成代码会怎么写?

Long start=System.currentTimeMillis();

//process start
........
........
........
........
// process end
Long end =System.currentTimeMillis();

if(end-start>200){
   log.info("process use time is "+(end-start))
}

现在看起来也不错?但是你有没有注意到,这样的代码很丑陋,想像一下,如果我们有六个环节。

那么代码应该就是这个样子。

// step 1
Long start=System.currentTimeMillis();

//process start
........
........
........
........
// process end
Long end =System.currentTimeMillis();

if(end-start>200){
   log.info("process use time is "+(end-start))
}

// step 2
Long start2=System.currentTimeMillis();

//process start
........
........
........
........
// process end
Long end2 =System.currentTimeMillis();

if(end2-start2>200){
   log.info("process use time is "+(end2-start2))
}

// step 3
Long start3=System.currentTimeMillis();

//process start
........
........
........
........
// process end
Long end3 =System.currentTimeMillis();

if(end3-start3>200){
   log.info("process use time is "+(end3-start3))
}

这种代码能忍么?哪有什么业务逻辑?如果你注意到我们之前讲过的Spring的IOC,其实就会想到,道理是一样的,可不可以不相关的业务逻辑踢出去,只保留我们正常要处理的业务逻辑?

这是代码的简洁之道,当然,并不仅仅是为了好看,还是为了统一的管理。比如说,半导说了,把切黄瓜时间大于200MS的过程都记录下来不合适,因为人是不可能在200MS之内切完黄瓜的,所以我们应该改成3分钟。

那么写代码的时候是不是要把所有的方法都改一遍?

你可以说我们用常量,但是假设我们有了更复杂的业务逻辑呢?比如说我想判断一下,一次切了几个黄瓜?

这就是我们要解决的问题,我们不用黄瓜和切菜来比喻,抽像一下,问题是这样的:

在系统中,大量的穿插着同样的操作,可能是在操作前,也可能是在操作后,我们并不关心具体的操作是什么,所以,有没有什么办法,对所有的操作都做统一的处理?

正确的提问,就是解决问题的90%.

其实很好办啊,怎么做?所有的工序,都不让每一个师傅自己去记录时间啦。

切菜的少楠师兄,洗菜的瑶瑶师姐,炒菜的沁修女神,上菜的然然师妹,都不用自己去记录时间啦。

谁来记?安排一个人后勤总管,比如说楠楠大总管 ,就坐在后厨里,每一道工序在执行之前,先到楠楠大总管这里登记。

楠楠大总管戴着墨镜,穿着西服和光滑的皮鞋,坐在办公桌面前,一份黄瓜要被洗,楠楠大总管就先记录一下当前的时间,然后扔给瑶瑶师姐,瑶瑶师姐洗完了,楠楠大总管再记录一下结束时间,再记录一下当前时间,再扔给少楠师兄。

就这样,所有的日志记录工作,都是由楠楠大总管一个人来完成,是不是很酷?

无论有多少道工序,只要是做饭,楠楠大总管都一直在努力的记录时间,可以统一的处理各种问题。

而少楠师兄,瑶瑶师姐们只需要关注自己的黄瓜,根本不需要记录时间。

这种方式是不是挺好的?但是想要实现这个功能,就必须要做到一点。

就是知道一个方法被调用 。然后在被调用之前,执行自己想要的方法,在被调用之后,执行自己想要的方法。

这种编程的方式,就叫做面向切面编程。

所以,再来看一下,什么叫做切面呢?

就是洗菜,切菜,炒菜,装盘,上菜这些环节之间,都切切切切切进去一张张卡片,在原来正常的业务流程中,加了很多埋点。

这就是切面。

在Java里,是通过静态代理,或者是动态代理的方式实现的。

这是另一个话题。

而理解AOP的关键点就在于两点。

第一点,我们为什么需要这种AOP

第二点,我们不是所有的编程都用AOP的方式来做

好了。不知道这个切黄瓜的讲解有没有讲清楚AOP的事情。

总之,当年我理解AOP的时候,满头雾水,直到我自己写了一个所有调用RMI服务响应时间的Util类的时候,才恍然大悟,原来这就是AOP啊。同样的,在Java中最常见的,还有拦截器,也是AOP应用最典型的场景。

咳咳,那个小姑娘是说对于切黄瓜还是没理解?好好好,我给你带几根黄瓜晚上示例一下。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容

  • 女主人公:瑶馨 ( 珍依 林静 璟萱为瑶馨的死党、闺蜜)关鹤云(瑶馨大学时男友)五年间发生了许多变故,因为各种原因...
    Marlboro媛阅读 934评论 0 1
  • 出污泥而不染,濯清涟而不妖。
    christinabj阅读 240评论 0 2
  • 最近学习web开发,参考知乎一些朋友的书单,给自己制订了一个阅读计划。 HTML5/CSS3 《响应式web设计:...
    lidroid本人阅读 696评论 0 7
  • 人的一生永远不要弄破两样东西,那就是信任和真情。信你的人,别骗;爱你的人,别伤! ...
    最阔爱的许子阅读 497评论 0 3
  • 于你:你可以不上学,但你不能不读书。我不希望在我说纳兰容若的时候你还在关心隔壁老王。 于爱情:你可以不浪漫,但你不...
    寂小欢阅读 318评论 0 0