简介:AOP (面向切面编程)是一种编程设计思想,旨在通过拦截业务过程的切面,实现特定模块化的能力,降低业务逻辑之间的耦合度。这一思路在众多知名项目中都有实践。AOP 只是一种概念,这种概念被应用在不同的场景下,产生了不同的实现。今天本文将和大家分享IOC-golang 的 AOP 原理与应用。
image.png

作者 | 李志信(冀锋)
来源 | 阿里开发者公众号

AOP 与 IOC 的关系

AOP (面向切面编程)是一种编程设计思想,旨在通过拦截业务过程的切面,实现特定模块化的能力,降低业务逻辑之间的耦合度。这一思路在众多知名项目中都有实践。例如 Spring 的切点 PointCut 、 gRPC的拦截器 Interceptor 、Dubbo 的过滤器 Filter。AOP 只是一种概念,这种概念被应用在不同的场景下,产生了不同的实现。
我们首先讨论比较具体的 RPC 场景,以 gRPC 为例。

image.png

针对一次 RPC 过程,gRPC 提供了可供用户扩展的 Interceptor 接口,方便开发者写入与业务相关的拦截逻辑。例如引入鉴权、服务发现、可观测等能力,在 gRPC 生态中存在很多基于 Interceptor 的扩展实现,可参考 go-grpc-middleware[1]。这些扩展实现归属于 gRPC 生态,限定于 Client 和 Server 两侧的概念,限定于 RPC 场景。

我们将具象的场景抽象化,参考 Spring 的做法。

Spring 具备强大的依赖注入能力,在此基础之上,提供了适配与业务对象方法的 AOP 能力,可以通过定义切点,将拦截器封装在业务函数外部。这些 “切面”、“切点” 的概念,都是限定于 Spring 框架内,由其依赖注入(也就是 IOC)能力所管理。

我想表达的观点是,AOP 的概念需要结合具体场景落地,必须受到来自所集成生态的约束。我认为单独提 AOP 的概念,是不具备开发友好性和生产意义的,例如我可以按照面向过程编程的思路,写一连串的函数调用,也可以说这是实现了 AOP,但其不具备可扩展性、可迁移性、更不具备通用性。这份约束是必要的,可强可弱,例如 Spring 生态的 AOP,较弱的约束具备较大的可扩展性,但实现起来相对复杂,发者需要学习其生态的众多概念与 API,再若 Dubbo 、gRPC 生态的适配于 RPC 场景的 AOP,开发者只需要实现接口并以单一的 API 注入即可,其能力相对局限。

上述 “约束” 在实际开发场景可以具象为依赖注入,也就是 IOC。开发者需要使用的对象由生态所纳管、封装,无论是 Dubbo 的 Invoker、还是 Spring 的 Bean,IOC 过程为 AOP 的实践提供了约束借口,提供了模型,提供了落地价值。

image.png

Go 生态与 AOP

AOP 概念与语言无关,虽然我赞成使用 AOP 的最佳实践方案需要 Java 语言,但我不认为 AOP 是 Java 语言的专属。在我所熟悉的 Go 生态中,依然有较多基于 AOP 思路的优秀项目,这些项目的共性,也如我上一节所阐述的,都是结合特定生态,解决特定业务场景问题,其中解决问题的广度,取决于其 IOC 生态的约束力。IOC 是基石,AOP 是 IOC 生态的衍生物,一个不提供 AOP 的 IOC 生态可以做的很干净很清爽,而一个提供 AOP 能力的 IOC 生态,可以做的很包容很强大。

上个月我开源了 IOC-golang [2]服务框架,专注于解决 Go 应用开发过程中的依赖注入问题。很多开发者把这个框架和 Google 开源的 wire [3]框架做比较,认为没有 wire 清爽好用,这个问题的本质是两个生态的设计初衷不同。wire 注重 IOC 而非 AOP,因此开发者可以通过学习一些简单的概念和 API,使用脚手架和代码生成能力,快速实现依赖注入,开发体验很好。IOC-golang 注重基于 IOC 的 AOP 能力,并拥抱这一层的可扩展性,把 AOP 能力看作这一框架和其他 IOC 框架的差异点和价值点。


点击链接查看原文,关注公众号【阿里开发者】获取更多福利!https://mp.weixin.qq.com/s/AjBhlLYF31xPHCBtR1ONVw

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。