说到AOP,这个东东现在已经不是一个新词汇了,我们拿一下百度词条来看看是下面的样子的:
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 |
从AOP这三个单词来看,它的定义还是非常准确的,就是面向切面编程。但是后面的这一堆解释:
通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 |
主要的变化就是把中间一段与具体的实现有关系的部分去掉。
通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。 |
这一段太过狭隘,已经远远不能满足软件技术发展的需要了,面向切面就面向切面,与什么预编译的方式有毛关系?与运行期代理有毛关系?与Spring、函数式编程有毛关系?
因此,今天悠然就把AOP的概念重新缕缕:
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过对某一领域进行高内聚低偶合方式进行实现,并通过非偶合的方式与其它业务逻辑进行整合,以对不同切面的实现逻辑进行隔离,从而使得不同领域的实现逻辑之间的耦合度降低,提高程序的可重用性、提高开发效率,同时也大大降低集成与整合难度的一种编程方法。 |
传统意义上的AOP,是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,来获得逻辑过程中各部分之间低耦合性的一些隔离效率,比如:常见的应用场景有:
确实,AOP的应用场景有许多许多,也取得了良好的应用效果,这个已经经过了充分的实践,许多书里也都进行了充分的阐述,这里不再赘述。
嗯嗯,今天的重点是这里,别人说得好的地方悠然说不过,因此最好的办法就是不说,悠然说别人不说的地方,这样就压力小多了:)
以下针对@红薯 的猜测纯属臆断,如有雷同纯属巧合:
在正式开始之前,我们来举个实践场景:
话说,在开源中国的博客列表中,每一篇博客是像下面一样展示的:
从这一块内容中,我们可以看到如下内容:
我们从看到的这些信息里面,可以猜一下@红薯 的表结果是怎么设计的:
表BLOG结构:
当然这里应该也有一些其他的字段,我们上面的图片里看不到,我们就当它们不存在。
我们再想想,估计@红薯 还有详细的记录,比如:谁评论的,评论的内容是什么?谁阅读的,是什么时候阅读的?谁点赞的,是什么时候点赞的?
于是就有了下面的表:
评论详情:
阅读详情:
点赞详情:
嗯嗯,@红薯 仔细想了一想感觉差不多了的样子,这个时候@红薯 缕着他的头发,点上一支烟进入了写代码的酸爽状态。
比如,功能是这样写的:
//博客点赞 保存点赞(博客标识,点赞者标识){ 博客biz.添加点赞(博客标识,点赞者标识); } class 博客biz{ 添加点赞(博客标识,点赞者标识){ 博客dao.增加点赞数(博客标识); 点赞详情dao.增加点赞详情(博客标识,点赞者标识); } }
伴随着一阵阵欢快的噼里啪啦键盘声,开源中国博客1.0 OK了。
于是红薯开始设计表结构:
表NEWS结构:
当然,考虑到新闻也有点赞,也有评语,也有阅读,于是下面的表结构也是需要的:
评论详情:
阅读详情:
点赞详情:
管呢,先运行起来再说,哥去泡个妹子放松一下,于是红薯打开了MAC,IPAD,IPHONE7S....
运行了一段时间,红薯觉得要加个动态功能,发现要在两边都增加代码,越来越觉得不对劲,于是拿起新买的《企业级JavaEE架构实践》翻看起来,唉当时看书的时候不仔细,这个用切面来解决不是挺好的?
于是红薯把表结构重构了一下:
评论详情:
阅读详情:
点赞详情:
另外增加一个动态表
红薯的手习惯的抬起来缕头发了,但是随着OSC功能的增加,头发已经几乎找不到了,红薯狠狠的把烟屁股拧进烟灰缸,是要彻底解决这个问题了,看起来还得读书啊,再翻翻《企业级JavaEE架构实践》,看看有没有啥思路。
Think Big, Start small , Scale Fast. |
好的软件是品出来的。 |
仔细看了几遍,红薯的眼睛忽然亮了起来,只要把所有的评论、点赞、评论、动态、以及其它杂7杂8的东西都让它高内聚,低耦合,我做博客只管做博客、做新闻只管做新闻,哪怕再做他多少个,也是仅仅关注我要做的东西,而把这些东西都做成一个个的切面让这些切面去完整的解决这些问题,这样我不就轻松了?原来虽然也引入了AOP技术,但是由于只是初级切面,所以只解决了部分问题,并没有彻底的解决问题。如果我能把切面也切到控制层、界面层,这样就可以真正的做到高内聚、松耦合,而且是真正的业务切面。
技术的切面还是初级的,业务层级的切面才是终级的。
具体实现起来,还是没有什么思路,听听悠然有没有什么思路?
通过上面对开源中国两个功能模块的分析,我们大致清楚了问题的症结所在,并通过对红薯的心路历程进行分析,大致引入了问题的解决思路,但是真正的落地却不是那么简单的。一个问题的抽象的程度越高,其通用性越好,但是它的易理解程度和易实现程度也就越难。我对实现者面对面多次沟通这个思路时,更多的时候看到的是他们茫然的眼神,以及多次感觉理解了,但是真正实现的时候却又达不到要求,直到许多次反复之后,才慢慢进入状态。
所以我会尽力讲清楚,但是不能保证你一定能理解到我内心所想。
我们在应用开发过程中,一部分是与具体的业务相关的,另外一部分它与具体的业务并不相关,但是在业务过程中又是有这样那样关系的。如果我们能把这些与具体业务没有直接关系,但又是对业务数据的一种维度的补充或描述能独立出来,想用或不想用仅在一念间,那么这个时候做软件就是一种享受了,而且业务和切面都可以独立变化,而不必考虑彼此的影响。
这个时候从开发效率来说,由于大家各自高内聚低耦合,所以开发、测试、验证、发布都会方便快速许多,集成的时候由于也不必有配置和代码及界面上的协作和引用,这样就可以大大的降低系统集成过程中的开发、测试工作,也避免了由此导致的一系列的可能出现的问题。
那么接下来,我们就用上面分析问题时的例子来阐述,如何解决这个问题,整个实现思路采用Tiny框架相关技术进行解决,非TINY技术平台或框架也是可以实现的,当然实现细节可能会有不同,需要相关的架构师进行相应的调整。
每个切面的内容都在自己的业务单元中实现,同时要能在能出来的时候它就能出来。
这里我们就拿上面说的一个场景"评论"来示例
评论详情:
既然是高内聚低耦合,那当然主是要统一界面的样式。
评价的使用场景一般来说是在显示完主要业务内容之后(如:博客、新闻、文档、软件、etc),可以进行评论,可以进行回复,可以进行引入,当然也要能把已经评论的内容显示出来。
但是需要搞清楚的是,这些内容的展现与人机交互过程明显与不同的业务内容没有一点关系,这也就为进行切面提供了基础。为了便于进行说明问题,这里采用AJAX模式进行解释,虽然采用非AJAX方式也是可以解释得通的,但是应用到的技术的复杂度与解释起来的困难都非常更加复杂。
举个例子,做出来的效果是类似下面的样子:
这个时候,问题就转换为,如何把当前要处理的业务类型和业务数据的标识让评论部分知晓,这个也非常简单,只要用下面的样子写一段模板即可:
#comment("BLOG",blog.blogId)上面的模板语言是指:现在我是在给一个BLOG类型的业务对象做评论,业务对象的标识是blog对象的blogId属性。
嗯嗯,这个时候较以前的开发,已经省了非常大的工作量了,只是简单的声明一下就可以了。
也就是说,博客功能是红薯先加的,而评论功能是红薯后加的。这里就出现一个问题:为什么后增加的功能,需要我在已经实现的妥妥的功能要进行调整??这岂不是说,你后面不断的增加功能,我这里都要不断的进行声明?虽然也有一定的道理,但是是不符合好莱坞原则的。实际上也是违反常理的===我是先来的,为什么要为你一个后到的做调整?我根本就不知道你的存在好么?!
出于我们对完美架构的追求以前我们不将就的态度,我们当然要更好的解决此问题。
我们可以在应用当中预设一些扩展点,但是具体扩展些什么东西我是不管的。
这个时候,我们就可以只在界面中增加如下的一段模板语言:
#extendPoint("VIEW","BLOG",blog.blogId)
上面的脚本表示,我这里是一个VIEW类型的扩展点,业务类型是BLOG,业务对象标识是blog对象的blogId属性。
然后由extendPoint决定往里面塞哪些东西。
这个时候,我只要在评论工程里增加如下的配置:
<extend-points> <extend-point type="page" order="10"> #comment(bizType,bizId) </extend-point> </extend-points>然后如果这个时候,我们又要增加一个留脚印的功能
我们只要增加一个留脚本的功能模块,在这个模块中增加下面的配置:
<extend-points> <extend-point type="page" order="9"> #footprint(bizType,bizId) </extend-point> </extend-points>
通过上面的改进,红薯同学再也不用薅头发了,原有的业务代码再也不用动,这功能居然自动在所有功能中自动出现了。
想到这里,悠然就深深的自责,早点给红薯出主意,红薯同学的一头黑发就留下来了。
当然,上面只是说了一个思想,真正的实现的时候用到的技术还是非常多的:如果本人没有说清楚,或者读者朋友们没有理解,本人深感自责,也希望同学们能够理解,并在下面的回复博客提问,本人定尽力给出解释。
有喜欢本人博客内容的同学请加关注,以便及时获知本人精品内容!