写点什么

解耦应用与依赖注入框架

  • 2010-01-21
  • 本文字数:1685 字

    阅读完需:约 6 分钟

由于 SOA、TDD 等众多因素的影响,依赖注入已成为近年来广为接受的软件开发方法,随之而来的则是依赖注入框架的大量应用(尤其是最近 Java EE 6 所包含的依赖注入)。Bob Martin 则通过实例演示了一种解耦应用代码与依赖注入框架的方法。

Dependency Injection Inversion 这篇文章中,Bob 大叔总结到:

…我可不想让依赖注入框架的代码散布在我的应用当中。相反,我想解耦框架与我自己编写的代码。

为了阐述这个问题,Martin 给出了一个示例,该示例围绕着 BillingService 类的创建展开,该类的构造方法定义了如下依赖:

复制代码
public class BillingService {
...
BillingService(CreditCardProcessor processor, TransactionLog transactionLog) {
this.processor = processor;
this.transactionLog = transactionLog;
}
...
}

首先,Martin 使用 Guice (Google 推出的依赖注入框架)创建 BillingService 类的实例:

复制代码
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
billingService.processCharge(2034, "Bob");
}

在解释完该段代码的一些细节后,Martin 给出这样一个事实:我们不得不显式地让 Guice 通过 injector 来创建 BillingService 的实例。这么做的结果就是:使用 BillingService 的代码不再依赖 BillingService 的依赖了(这很好),但却依赖 Guice 了。

是不是有利就有弊呢?Martin 的回答是肯定的:

依赖注入不过是依赖倒置(Dependency Inversion)的一个特殊情况而已。我认为依赖倒置非常重要,因此打算转换对 Guice 的依赖。我可不想让那么多的 Guice 依赖搞乱了我的代码。

之后,他向我们展示了如何通过工厂对象来控制并降低应用对 DI 框架的依赖:

复制代码
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService.factory = new BillingServiceFactory(injector);
}
...
// Deep in the bowels of my system.
BillingService billingService = BillingService.factory.make();
billingService.processCharge(2034, "Bob");

为什么这种方式比较好呢,Martin 说到:

我喜欢这么做,因为现在所有的 Guice 代码都放在了同一个地方,而非散布在应用的各个角落,这是通过工厂实现的。不仅如此,如果将 Guice 替换成其他 DI 框架,我会明确知道需要修改哪些类以及如何修改他们。通过这种方式达到了应用与 Guice 解耦的目的。

要澄清的一点是:在所有的示例中,BillingService 本身都坚持着依赖注入原则,而 BillingService 到底使用的是依赖(CreditCardProcessor 及 TransactionLog)的何种实现其本身是不得而知的。为了说明这一点,他在文章的最后通过 JUnit 对 BillingService 进行了测试,在测试中仅仅使用了简单的 TransactionLog 和 CreditCardProcessor 实例对其进行注入,最后无论应用使用何种依赖注入手段,测试结果都是正确的。

Gary Bernhardt 就这个测试也给出了一篇文章,提到在Java 这种静态类型语言中这么做需要慎之又慎,但对于Python 之类的动态语言就无所谓了。

你是否使用依赖注入呢?是否使用DI 框架呢?不管答案如何,以上这种做法是否与你产生共鸣了呢?

查看英文原文: Decoupling Your Application From Your Dependency Injection Framework

有 InfoQ 读者对 Bob 大叔的这种做法提出了不同的观点:

来自 InfoQ 英文站的读者 monser corp 说到:

我想知道 Bob 大叔在过去几年编了多少代码?

恩,这是一种典型的”顾问式“做法:了解一项新技术,拿起来玩弄一下,然后发表在博客上来满足自己的虚荣心。在我做过的很多项目(使用了 Spring)中,只有一个类会依赖于 Spring:获取 Context 并启动应用。99.99% 的代码都不知道 Spring 或 Guice 是啥(如果不是使用了 Spring 的某些库的话,IoC 容器与 Log4J 根本就没啥区别)。如果真的想将代码与容器解耦,你需要重新考虑设计与实现,而非使用另一个工厂。

作为读者的您有何高见呢?这里,译者推荐您先去阅读 Bob 大叔的原文,然后将您的高见发表在这里。

2010-01-21 06:364347
用户头像

发布了 88 篇内容, 共 272.5 次阅读, 收获喜欢 9 次。

关注

评论

发布
暂无评论
发现更多内容

德国 building IoT 2024 峰会:天谋科技围绕 IoTDB 的时序数据管理解决方案前沿探索

Apache IoTDB

基于高德地图的电子围栏、地图搜索嵌入

五陵散人

地图 高德地图 电子围栏

大模型基础应用框架(ReACT\SFT\RAG)创新及零售业务落地

京东零售技术

人工智能 算法 大模型 agent ChatGPT

企业架构设计原则之理念领先性

凌晞

架构设计原则

融云 IM 史无前例五折优惠!

融云 RongCloud

万字长文讲解关于LowCode你需要知道的一切

canonical

DDD 低代码 软件架构 可逆计算 Nop平台

一文读懂Penpad 以 Fair Launch 方式推出的首个资产 PEN

BlockChain先知

百度AI,能否“投”出未来?

自象限

百度 AI

SpringBoot混淆代码,防止反编译代码泄露

源字节1号

开源 软件开发 前端开发 后端开发 小程序开发

2023,九章云极DataCanvas的澎湃时刻

九章云极DataCanvas

九章云极DataCanvas公司出席WBBA 2024宽带发展大会

九章云极DataCanvas

九章云极DataCanvas公司牵手国家超算互联网,实现算法与算力一体化服务

九章云极DataCanvas

壹陆锋芒,韧性成长 | 博睿数据16周年庆典圆满落幕!

博睿数据

AIGC下一步:如何用AI再度重构或优化媒体处理?

不在线第一只蜗牛

视频 媒体服务 AIGC 人工智你

一文读懂Penpad 以 Fair Launch 方式推出的首个资产 PEN

加密眼界

再聊对架构决策记录的一些思考

疯狂架构

架构设计实战 架构决策记录 ADR

解耦应用与依赖注入框架_Java_Mike Bria_InfoQ精选文章