为什么要有 Sping AOP

本贴最后更新于 2310 天前,其中的信息可能已经事过境迁

一、Web 开发演进到一定阶段的痛点

我们在初学习 Java Web 的时候,应该都经历了以下的阶段:

(1)一个主函数 main 中包含了所有的方法;

(2)将主函数中的方法进行拆分封装,抽取为一个个的方法;

(3)按照每一个方法不同的功能分为一个个的类;

(4)有了 MVC 模型之后,我们按照 MVC 的思想将我们的代码拆分为三层,每层负责不同的功能,进行分门别类的管理;

很多程序的功能还可以通过继承关系而得到重用,进一步提高了开发效率。再后来,又出现了各种各样的设计模式,使设计程序功能变得得心应手。

在面向对象的大环境下,我们可以很好地组织代码,通过继承、封装和多态的思想去设计一个个比较让人满意的类,但是我们慢慢的发现,我们的代码中逐渐多了很多重复性的代码,有人可能会想到,把这些重复性的代码抽取出来不就好了吗?是这样的,我们看一下这种思路的一个实例:

可以看到,上述代码功能上确实可以实现,但是我们的业务代码已经被这些非核心的代码所混淆,并且占据了大量的空间!显然这种显示的调用过程成为了我们开发过程中的一个痛点,如何将类似这种的非核心的代码剥离出去成为一个迫切需要解决的问题!

不仅如此,假设我们要控制每一个方法的访问权限,只允许一部分用户进行访问,在不考虑过滤器的情况下,我们是不是需要在每一个方法开始的时候判断用户是否具有该权限,如果有的话就可以进行访问,如果没有的话,就不允许进行访问!

诸如此类,还有数据库事务的控制,数据库连接的创建和关闭等等,这些都充斥这大量重复性的模板代码!一个很现实的问题,假如有一天,业务需求不需要进行日志记录了,那岂不是我们需要把以前写的代码,全部删掉!想想都是一件很可怕的事情!

二、使用设计模式进行一次改进

如果你对设计模式玩的比较熟的话,这个时候你可能会想到使用 JDK 动态代理设计模式(动态代理设计模式可以在原有的方法前后添加判断、选择或其他逻辑)对上述代码进行改进,(关于什么是 JDK 动态代理,这里不再详细赘述,有不懂的的可以查阅相关资料具体了解一下!)修改后的代码如下:

上述为代理类,红色框中圈出的表示以前业务中的模板代码,这里直接输出表示方法执行的过程,以前的 UserServiceImpl 修改为如下(直接用输出的方式表示方法执行了):

测试代码如下:

上述的执行结果可以看出,每次调用一个方法的时候前后都会调用我们期望的代码,实现了我们期望的标准!

通过 JDK 动态代理的方式,让我们彻底的解放出来了!

三、撕开披在 AOP 身上的一层薄纱

上述过程中,我们看到在动态代理的 invoke 方法里边,我们相当于在原有方法的调用前后“植入”了我们的通用日志记录代码,如果你看到这一层的话,那么恭喜你!你已经领悟到了 AOP 思想最核心的东西了!

上述抽取公共代码其实就是 AOP 中横切的过程,代理对象中在方法调用前后“植入”自己写的通用日志记录代码其实就是 AOP 中织入的过程!这个织入的代码也就是横切逻辑,织入代码的过程其实就是在原有的方法前后增强 原方法的过程!总的来说,我们想解决我们开发中的痛点,然后就出现了一种技术,这种技术手段就是 AOP。

AOP 书面表述如下:

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容(Spring 核心之一),是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

四、AOP 与 Spring AOP 的关系

AOP 是一种思想,不同的厂商或企业可能有不同的实现方式,为了更好的应用 AOP 技术,技术专家们成立了 AOP 联盟来探讨 AOP 的标准化,AOP 联盟定义的 AOP 体系结构把与 AOP 相关的概念大致分为由高到低、从使用到实现的三层关系,AOP 联盟定义的 AOP 体系结构如下图:

在 AOP 联盟定义的 AOP 体系结构下有很多的实现者,例如:AspectJ、AspectWerkz、JBoss AOP、Spring AOP 等。Spring AOP 就是在此标准下产生的,这里不再深入 Spring AOP 的其他概念,这些概念会在后期探讨。

五、其他问题

上述通过动态代理的方式实现了简单的 AOP,但是值得注意的是,我们的代理目标对象必须实现一个接口,要是一个接口的实现类,这是因为再生成 Proxy 对象的时候这个方法需要一个目标对象的接口:

显然,有些特殊的场景使用 JDK 动态代理技术的话,已经不能够满足我们的场景了,又遇到痛点了!凡事不劳我们操心的 Spring 框架已经替我们想到了,既然你有这种需求,我就使用一种技术帮你实现就行了,Spring 在这里使用 CGLib 动态代理的方式实现了我们的这种诉求。

CGLib 采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势的织入横切逻辑。

看到这里,我们会想以后会不会还有 CGLib 解决不了得问题啊?我们已经很清楚的知道了对于 Spring AOP 来说,使用到了 JDK 动态代理技术和 CGLib 动态代理技术,这两种方式已经实现了我们绝大多数的场景,如果还有不能满足的需求,迫切需要解决的痛点,我相信 Spring 还会采用相应的技术来满足这些场景。

六、总结

上述的过程,大致从一个侧面探讨了一下我们为什么需要 AOP,AOP 与 Spring AOP 的关系以及 Spring AOP 两种实现的方式(JDK 动态代理和 CGLib 动态代理)。

Spring 不尝试提供最为完善的 AOP 实现,它更侧重于提供一种和 Spring IOC 容器整个的 AOP 实现,用于解决实际的问题,在 Spring 中无缝的整合了 Spring AOP、Spring IOC 和 AspectJ。

当然,Spring AOP 的内容不仅仅有这些!例如:我们在使用 Spring AOP 的时候只是简单的配置了一下(通过 XML 或注解进行配置),没有像 ProxyDemo 测试类中的那样,还需要我们手动的调用 ProxyFactory 来创建代理对象,然后调用我们的目标方法,其实 Spring AOP 在内部已经帮我们把这些事情做好了,具体的原理后期会继续探讨。另外,Spring 如何整合 Spring IOC 和 AOP 的,这一点也会在后期探讨。

最后补充一下!动态代理或者设计模式重要吗?很重要!Spring AOP 用到了动态代理,Spring 事务管理用到了动态代理,MyBatis 数据库连接池用到了动态代理,MyBatis 创建 Mapper 用到了动态代理等等,你说重要不!要想踏进这些高层框架原理的大门,设计模式首先是我们的第一段台阶!

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 165 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    946 引用 • 1460 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖
  • AOP
    21 引用 • 13 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • AWS
    11 引用 • 28 回帖 • 11 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 637 关注
  • Access
    1 引用 • 3 回帖 • 7 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 442 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • 反馈

    Communication channel for makers and users.

    126 引用 • 929 回帖 • 266 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    132 引用 • 876 回帖 • 4 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 735 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    169 引用 • 1527 回帖
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 20 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 299 关注
  • gRpc
    11 引用 • 9 回帖 • 89 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 819 关注
  • 音乐

    你听到信仰的声音了么?

    61 引用 • 512 回帖
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 661 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    5 引用 • 7 回帖
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 610 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    729 引用 • 1278 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    946 引用 • 1460 回帖
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖 • 3 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 1 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 3 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖