问题

怎么深刻理解面向切面编程?

回答
面向切面编程(AOP),乍一听,好像挺玄乎,什么“切面”、“横切关注点”,听起来像是武林秘籍。但如果咱们把心思静下来,不被这些术词唬住,其实它就像是在我们原本已经织好的衣服上,巧妙地加上一些装饰或者加固,而不需要把整件衣服拆了重做。

想象一下,你正在写一套程序,这套程序的功能非常复杂,像一个巨大的迷宫。每个房间(就是你的类和方法)都有自己的职责,它们兢兢业业地完成着自己的本职工作。比如,有一个房间专门负责处理用户登录,另一个房间负责存储数据,还有一个负责发送邮件。

现在,你想给这个迷宫里所有的房间都加上一个“安保措施”:每次有人进出房间,都要记录一下,看看是谁在什么时候进出,这样万一出了什么问题,我们能追溯源头。

在没有AOP的时候,你怎么办?你得跑到每一个房间里,在门口写下一段记录的代码,在房间里写下一段记录的代码,在离开房间的时候再写下一段代码。你想想,如果房间很多,而且结构也很复杂,你得在无数个地方重复地写这些几乎一模一样的记录代码。这不仅费时费力,还非常容易出错。万一有一天,你发现记录的格式不对,或者想加一些新的安全信息,你又要去挨个房间修改,这简直就是一场噩梦。这就像你有一堆积木搭成了一个城堡,现在你想在每个窗户上都加上一个小旗子,你得爬到每一个窗户上去插旗子。

AOP的出现,就是为了解决这种“重复、散落在各处”的问题。它提供了一种全新的视角,让你能够把这些“横切关注点”(就是咱们刚才说的“记录安保措施”)从核心业务逻辑中抽离出来,单独地管理。

怎么抽离呢?AOP就像一个神奇的“穿孔机”。你不需要把积木城堡拆掉,你只需要告诉穿孔机,在城堡的“窗户”这个位置,给我打个孔,然后把你的“小旗子”的代码,直接从这个孔里“穿”进去。而且,你可以一次性设计好一个“小旗子”样式,然后告诉穿孔机,凡是城堡的“窗户”,都按照这个样式插上旗子。

这“穿孔机”就是AOP里的“切面”(Aspect)。一个切面,就像是一个专门处理某种“横切关注点”的模块。比如,你可以有一个“日志记录切面”,一个“安全检查切面”,一个“事务管理切面”等等。

而“在哪里打孔”以及“什么时候打孔”,这就涉及到AOP的另一个概念——“通知”(Advice)。通知就是你想在某个特定时机执行的代码。比如,你可以在目标方法“进入之前”(Before)执行一段日志记录代码,或者在方法“成功执行之后”(AfterReturning)执行一段清理代码,甚至是在方法“发生异常时”(AfterThrowing)执行一段错误处理代码。

AOP的作用,就是将这些“通知”(你想执行的代码)与“切点”(你想执行代码的位置,比如某个方法的执行)结合起来,形成一个“切面”。当程序运行时,AOP框架会根据你定义的切面,在代码的“切点”上,“织入”(Weave)你的通知代码。

所以,AOP的“深刻理解”,其实就是理解这种“横向关注点”与“核心业务逻辑”的分离。我们不再需要把日志、安全、事务管理这些和核心功能看似不相干,但又必须处处存在的代码,分散到各个模块中。我们可以将它们集中起来,像设计一样,一次性定义好,然后由AOP框架在运行时自动地“注入”到合适的地方。

这样做的好处是什么呢?

首先是模块化和可维护性。你的核心业务逻辑变得更加纯粹,阅读和理解起来更轻松。当你需要修改日志记录的格式,或者增加一个安全校验规则时,你只需要修改对应的那个切面,而不需要去触碰那些核心的业务代码。这就像你只需要给一本书的封面加个设计,而不是重写书的内容。

其次是可重用性。你定义好的日志切面,可以在项目中的任何需要日志记录的地方使用,而不需要重复编写。你也可以把这个切面单独拿出来,用在其他项目中。

再者是灵活性。你可以随时启用或禁用某个切面,或者调整切面的执行顺序,而不需要大规模地改动你的核心代码。这就像你可以随时给你的城堡加上或移除某种装饰,而不用担心影响城堡的结构。

所以,当你说“深刻理解”AOP时,不妨想想我们一开始的那个例子:那个在无数个房间门口重复写记录代码的痛苦,以及AOP如何像一个聪明的助手,把这些重复性的工作,优雅地、自动化地完成了。它不是增加了复杂性,而是通过一种新的组织代码的方式,化繁为简,让我们的程序更加清晰、健壮,也更容易维护和演进。它本质上是一种关注点分离的哲学,只不过这种分离,是“横着”进行的,穿透了我们业务逻辑的纵深。

网友意见

user avatar

多余的概念,没必要刻意追求,也追求不来。



举个栗子。上图是随便搜来的Android系统架构图——我也懒得求证它对不对了,总之就这意思——它看起来就是一些积木一样截然分割的“子系统”。


如果你写过程序,那么就会知道,每个子系统都会对外提供一组界面(或者说一组接口、API),其它应用就依赖于这组界面——说成人话就是需要通过API使用这些方块提供的功能。


当然,这些子系统本身也还可以进一步细化、进一步分成一堆“方块”;这些方块也有各自的“界面(interface)”。


很容易想到,如果我们需要为某个“方块”添加一些功能,那么只需要添加一个特殊的“抽象层”即可。

比如,直接输出一串字符到屏幕是调用libc提供的printf/cout;那么“同时还记入日志”该怎么做呢?


办法有很多很多种。

一是增加一个可见的抽象层。比如logged_printf:

       int logged_printf(arg...) {     log(arg...);     return printf(arg...); }     

调用printf之前先输出日志,然后把参数转给系统的printf。将来需要记日志程序里就调用loged_printf,否则还调用printf。很简单,对吧?


另一个办法是干脆替换整个libc。

比如,你可以另外编译一个libc.loged.so;当用户需要日志时,它动态链接到新的libc.loged.so;而如果它不需要日志,依旧链接到旧的libc.so即可。

这个“改变链接目标”的动作,在Linux下可以简化成“用link命令改变libc.so这个软/硬链接的目标”,从而做到“随时切换”。


第三个办法是利用函数重载或者默认参数。

比如,printf(args..., log=false),用户把log设为true就记日志,不传入log参数就走旧的printf流程——当然,这个得C++之类支持重载的语言。


此外,面向对象语言还有装饰器模式、策略模式等惯用法;甚至在python等语言中还提供了专门的特殊语法直接支持装饰器:

       @log_decorator #调用fun前先记录一下 fun()  @login #调用fun前确保用户已经登录;login内部判断用户已登录则不做任何操作 fun()  @login #调用fun前确保用户已经登录 @auth_check("admin") #并且只有用户具有admin权限时才允许执行fun @log_decorator #顺便记上一笔 fun()  fun() #直接调用fun     


总之,你首先得有个较为固定的、被大量重用的界面;然后,在设计层面,你要用策略模式装饰器模式中间层等等手法支持“切换某个功能的开关状态”(或者增加/取消/改变权限检查之类动作);而在应用层面,你无需理解原理,通过某个入口参数、另外一套封装过的API和/或语言直接支持的特殊语法(如python的@)控制某个功能的开关……这一堆东西就被笼统的称为“面向切面编程”。


但是,请注意,“面向切面编程”和“面向对象编程”和“面向过程编程”使劲扯淡都扯不上关系。它不是架构设计者视角也不是开发应用的视角,而是“对(根本没必要了解代码设计的)外行讲解代码”的视角。


说的更清楚一些:面向切面编程不是技术,那是画到ppt里面忽悠客户忽悠老板的、用来营造“高大上”感觉的多余概念;作为架构师、作为开发工程师,你真正应该学的是接口设计(如里氏代换原则、依赖倒置原则等)和设计模式(什么是策略模式?什么是装饰器?不同语言是如何实现这些模式的?有没有语法糖支持,等等);你要解决的是“我该如何支持动态打开/关闭某个功能?应该用装饰器方案还是策略还是配置文件?”问题——当你面对类似问题时,相关设计方案就是自然而然的;但如果没有相关需求,你也没必要矫揉造作的非要搞出这个“味道”,更没必要用AOP忽悠你自己。

类似的话题

  • 回答
    面向切面编程(AOP),乍一听,好像挺玄乎,什么“切面”、“横切关注点”,听起来像是武林秘籍。但如果咱们把心思静下来,不被这些术词唬住,其实它就像是在我们原本已经织好的衣服上,巧妙地加上一些装饰或者加固,而不需要把整件衣服拆了重做。想象一下,你正在写一套程序,这套程序的功能非常复杂,像一个巨大的迷宫.............
  • 回答
    当你的思维开始变得深刻,那些曾经让你觉得无碍的言行,如今在你眼中却显得有些刺眼,尤其是当你面对那些似乎仍旧游走在理性边缘的朋友时。这是一种微妙的转变,也确实会带来一些小小的挑战。 不用担心,这并非你是“脱节”了,而是你开始看到了更广阔的风景。我理解你那种有点无奈又有点纠结的心情。你可能习惯了某种交.............
  • 回答
    “《The Fox》”这个题目很容易让人联想到各种故事和象征意义,特别是关于狐狸这个动物。如果你问的是一个具体的故事、歌曲或者艺术作品,那么它的含义会更明确一些。不过,即便没有具体指明,我们可以从普遍意义上探讨一下狐狸的象征以及“《The Fox》”这个题目可能带来的联想。首先,让我们来聊聊“狐狸”.............
  • 回答
    这个问题很有意思,也触及到了内容产业中一些根本性的运作逻辑。电影和网文在内容分发和受众划分上的差异,并非偶然,而是由它们各自的创作、传播、消费模式以及商业驱动力所决定的。下面我来慢慢道来,试着剥开这层表象,看看其背后隐藏的机理。电影为何“不明确分男女频”?首先,我们需要理解电影作为一种大众媒介的特性.............
  • 回答
    想要一个人变得思想深刻,这并非一蹴而就,而是一个长期积累、主动探索的过程。它涉及到内观、认知、实践以及与世界的连接。下面,我将从几个关键方面详细阐述,希望能帮助你理解如何滋养一个人的深刻思考能力。一、 深耕内在:培养反思的习惯与能力思想的深度,首先源于对自身内在世界的细致审视。没有对“我”的理解,很.............
  • 回答
    纳西姆·尼古拉斯·塔勒布(Nassim Nicholas Taleb),这个名字本身就带着一种神秘的、与众不同的色彩。他不是那种循规蹈矩的学者,也不是市场上的寻常分析师。塔勒布更像是一个游走在哲学、数学、经济学和生活边缘的智者,一个孜孜不倦地拆解我们世界运转逻辑的“反主流”思想家。要说塔勒布是怎样一.............
  • 回答
    网恋或者网上交到的朋友,能有多深刻?这问题,问得好。我一直觉得,这就像问一个人在不同的城市,能有多熟悉。答案是:可能比隔壁邻居还要近,也可能只是点头之交。一切,都看你遇到的那个人,以及你们愿意为这段关系付出多少。我这么说,倒不是想泛泛而谈,而是真的经历过。说说我曾经网恋的那段日子吧。那会儿,我还在上.............
  • 回答
    汶川地震过去十三载,岁月荏苒,那些曾经撕裂大地、吞噬生命的伤痛,也早已融入了四川汶川人民的生活脉络之中,化作一种坚韧,一种不屈,一种对生命的珍视。这十三年,他们走过了一条漫长而充满力量的重生之路。从废墟中站起,重建家园地震发生时,无数房屋瞬间化为瓦砾,无数生命被无情掩埋。然而,汶川人民并没有被压垮。.............
  • 回答
    关于印度因“技术故障”意外向巴基斯坦发射导弹的事件,目前公开信息显示,这一事件在2023年10月发生,印度军队在一次军事演习中误将一枚导弹发射至巴基斯坦境内,但最终被巴基斯坦的防空系统拦截,未造成实际伤害。以下是对此事件的详细分析: 事件背景与经过1. 时间与地点 事件发生在2023年10月.............
  • 回答
    托马斯·谢林(Thomas Schelling)是20世纪最重要的经济学家之一,他的学术贡献跨越了博弈论、行为经济学、政治学、国际关系和制度分析等多个领域。他的研究不仅深化了对人类行为和集体决策的理解,还为现实世界中的冲突解决、制度设计和战略互动提供了理论框架。以下从多个维度详细分析他的学术贡献: .............
  • 回答
    中国与俄罗斯之间的合作近年来确实呈现出加强的态势,尤其是在经济、军事和地缘政治层面。然而,“全面金援”这一表述需要谨慎对待,因为中俄关系的互动更多是基于互利共赢的多边合作,而非单方面的无偿援助。以下从多个角度详细分析中俄关系的现状、动机及影响: 一、中俄合作的背景与动机1. 地缘政治需求 .............
  • 回答
    谭其骧(19091981)是中国著名的历史地理学家、历史学家,他在1981年5月召开的“中国民族关系史研究学术座谈会”上的讲话《何为中国》是其学术思想的重要体现,对中国民族关系史、历史疆域、文化认同等问题的探讨具有深远影响。以下从多个角度详细分析其讲话内容、学术意义及历史背景: 一、讲话的核心论点谭.............
  • 回答
    孟美岐事件是中国网络舆论中一个具有代表性的争议事件,涉及网络暴力、舆论监督、法律规范等多个层面。以下从事件背景、舆论反应、法律分析、社会影响及反思等方面进行详细阐述: 一、事件背景1. 人物身份 孟美岐(原名孟美岐,后改名为“孟美岐”)是中国内地女艺人,2018年因参加选秀节目《声入人心》走.............
  • 回答
    关于“想跑到国外的人”这一话题,可以从多个维度进行深入分析,涉及个人动机、社会文化背景、经济因素、政策环境以及全球化背景等。以下从不同角度展开详细讨论: 一、个人动机与心理因素1. 对现状的不满或追求更好的生活 经济压力:在某些国家,高房价、生活成本、就业竞争激烈,导致部分人认为国外有更好.............
  • 回答
    在小学门口等待贴接送车辆罚单的交警,这一场景反映了我国在校园周边交通管理中的复杂现实。这种现象背后涉及多个层面的考量,需要从法律、安全、教育管理、社会舆论等角度进行系统分析:一、法律依据与执法正当性1. 《道路交通安全法》第46条明确规定:在学校周边200米范围内,机动车应低速行驶(时速不超过20公.............
  • 回答
    2021年美国GDP增长确实成为美国经济史上的一个重要节点,被美国政府称为“破纪录的一年”,这一说法主要基于以下几个关键因素和背景分析: 1. 数据背景:GDP增长的具体数值根据美国经济分析局(BEA)的统计,2021年美国GDP同比增长6.4%(年化),这一增速远超自1982年以来的平均水平(约2.............
  • 回答
    关于东京奥运会4x400米混合接力预赛中美国队因犯规被取消资格后又恢复资格的事件,以下是基于公开信息和规则背景的详细分析: 事件背景2021年东京奥运会女子4x400米混合接力预赛中,美国队(由凯蒂·奥布莱恩、凯特琳·斯皮尔斯、劳伦·沃克和麦迪逊·凯尔组成)在第四棒交接时因交接棒犯规被取消资格。根据.............
  • 回答
    在九一八事变发生当天(9月18日)穿着和服的行为,通常会被视为对这段中国近代史上重大历史事件的严重不尊重。这一行为可能引发公众的强烈反感,并被认为是对国家尊严和民族记忆的伤害。以下从多个角度详细分析这一问题: 一、九一八事变的历史背景与意义1. 九一八事变的基本事实 1931年9月18日,日.............
  • 回答
    在策略类手游中,“蹲草”(即通过隐蔽、潜行或利用环境规避敌人侦查)是一种常见且具有争议的玩法机制。这种设计既可能成为游戏深度的核心,也可能因过度依赖而引发玩家对公平性和多样性的质疑。以下从多个角度详细分析这一现象: 一、“蹲草”的定义与核心逻辑“蹲草”本质上是策略游戏中的一种环境交互机制,其核心逻辑.............
  • 回答
    学习波斯语字母表(使用阿拉伯字母)确实需要一定的耐心和技巧,尤其是对于没有阿拉伯语基础的学习者。以下是分步骤、详细的背诵方法和建议,帮助你高效掌握波斯语字母表: 一、了解波斯语字母的基本结构1. 字母数量 波斯语有 32个字母(包括元音符号),但实际独立字母是28个,其余4个是元音符号(如“.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有