写点什么

解耦应用与依赖注入框架

  • 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:364282
用户头像

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

关注

评论

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

英特尔技术发力:着眼10倍封装密度提升,30%~50%晶体管密度提升,布局非硅基半导体

科技新消息

【HZERO微服务平台1】开源免费的企业级PaaS平台

qiaoxingxing

签约计划第二季

实体链接在小布助手和OGraph的实践应用

安第斯智能云

人工智能 深度学习 算法 nlp 知识图谱

ZooKeeper 分布式锁 Curator 源码 05:分布式读写锁和联锁

程序员小航

Java 分布式锁 curator

node.js中利用IPC和共享内存机制实现计算密集型任务转移

RingCentral铃盛

CSS之选择器(五)

Augus

CSS 12月日更

火遍全网的「蚂蚁呀嘿」教程开源了!

百度开发者中心

开源

【HZERO微服务平台5】JHipster接入HZERO

qiaoxingxing

签约计划第二季

全新“支付方式”来了,数字货币六大行公开支持,安全且转账免费

CECBC

XML数字签名实践篇

RingCentral铃盛

超写实“龚俊数字人”上线,百度智能云助力各行业打造定制数字人

百度开发者中心

人工智能

如何在建木CI中使用Vault管理密钥

Jianmu

DevOps CI/CD 开源软件

【HZERO微服务平台2】源码分析之网关

qiaoxingxing

签约计划第二季

如何优雅地在Vue页面中引入img图片

CRMEB

AOP在JavaScript和TypeScript中的应用

RingCentral铃盛

值得收藏!2021百度开源技术干货大汇总

百度开发者中心

开源 2021 内容合集 技术专题合集 百度开源

【HZERO微服务平台3】源码分析之oauth服务token生成、校验、获取信息、传递

qiaoxingxing

签约计划第二季

跨平台多主机键鼠共享

Arch

Hoo虎符研究院 | 区块链简报 20211213期

区块链前沿News

区块链 Hoo 虎符交易所

简单3步,OpenHarmony上跑起ArkUI分布式小游戏

HarmonyOS开发者

OpenHarmony

区块链产业规模约达50亿元,已成为数字经济发展重要引擎

CECBC

如何高效完成HarmonyOS分布式应用测试?|HDC2021技术分论坛

HarmonyOS开发者

HarmonyOS ArKUI 3.0

恒源云(GPUSHARE)_CV领域之几何变化

恒源云

深度学习 CV

深入研究【HZERO微服务平台】开源免费的企业级PaaS平台

qiaoxingxing

内容合集 签约计划第二季

Go语言学习查缺补漏ing Day8

恒生LIGHT云社区

golang 编程语言 Go 语言

XML数字签名原理篇

RingCentral铃盛

降低成本对技术组织意味着什么?

田晓亮

云计算 serverles

java实现数据导出

卢卡多多

28天写作 数据导出 12月日更

【HZERO微服务平台4】源码分析之admin服务刷新路由、权限、swagger的过程

qiaoxingxing

签约计划第二季

首个国产元宇宙“希壤”来临,百度成了先锋!

CECBC

百度开源一款基于 Git 的多仓库管理工具:MGit

百度开发者中心

git 开源

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