我目前正在用nodejs创建一些实验性项目。我用Spring编写过很多Java EE web应用程序,非常欣赏依赖注入的便利性。
现在我很好奇:如何对节点进行依赖注入?或者:我真的需要它吗?因为编程风格不同,是否存在替代概念?
到目前为止,我谈论的是一些简单的事情,比如共享数据库连接对象,但我还没有找到一个让我满意的解决方案。
我目前正在用nodejs创建一些实验性项目。我用Spring编写过很多Java EE web应用程序,非常欣赏依赖注入的便利性。
现在我很好奇:如何对节点进行依赖注入?或者:我真的需要它吗?因为编程风格不同,是否存在替代概念?
到目前为止,我谈论的是一些简单的事情,比如共享数据库连接对象,但我还没有找到一个让我满意的解决方案。
当前回答
事实上,你可以在没有IoC容器的情况下测试node.js,因为JavaScript是一种真正动态的编程语言,你可以在运行时修改几乎所有东西。
考虑以下几点:
import UserRepository from "./dal/user_repository";
class UserController {
constructor() {
this._repository = new UserRepository();
}
getUsers() {
this._repository.getAll();
}
}
export default UserController;
因此,您可以在运行时覆盖组件之间的耦合。我认为我们应该以解耦JavaScript模块为目标。
实现真正解耦的唯一方法是删除对UserRepository的引用:
class UserController {
constructor(userRepository) {
this._repository = userRepository;
}
getUsers() {
this._repository.getAll();
}
}
export default UserController;
这意味着你需要在其他地方进行对象合成:
import UserRepository from "./dal/user_repository";
import UserController from "./dal/user_controller";
export default new UserController(new UserRepository());
我喜欢将对象组合委托给IoC容器的想法。您可以在文章《JavaScript中依赖倒置的当前状态》中了解更多关于此思想的内容。这篇文章试图揭穿一些“JavaScript IoC容器神话”:
误解1:JavaScript中没有IoC容器的位置 误解2:我们不需要IoC容器,我们已经有模块加载器了! 误解3:依赖倒置===注入依赖
如果你也喜欢使用IoC容器的想法,你可以看看InversifyJS。最新版本(2.0.0)支持多种用例:
内核模块 内核的中间件 使用类、字符串或符号作为依赖标识符 常数值注入 类构造函数的注入 工厂注入 汽车工厂 提供程序的注入(异步工厂) 激活处理程序(用于注入代理) 多注射 标记绑定 自定义标记装饰器 指定绑定 上下文绑定 友好的异常(例如循环依赖)
你可以在InversifyJS上了解更多。
其他回答
这取决于应用程序的设计。显然,你可以做一个类似java的注入,在那里创建一个类的对象,并将依赖项传递给构造函数,就像这样。
function Cache(store) {
this._store = store;
}
var cache = new Cache(mysqlStore);
如果你不是在javascript中做OOP,你可以做一个init函数来设置一切。
然而,还有另一种方法可以采用,这种方法在基于事件的系统(如node.js)中更为常见。如果您可以将应用程序建模为仅(大多数时候)对事件进行操作,那么您所需要做的就是设置所有内容(我通常通过调用init函数来完成)并从存根发出事件。这使得测试相当容易和易读。
我认为其他的文章在使用DI的论证方面做得很好。对我来说,原因是
注入依赖项而不知道它们的路径。这意味着如果您更改磁盘上的模块位置或将其与另一个模块交换,则不需要触及依赖于该模块的每个文件。 它使模拟依赖关系以进行测试变得更加容易,而不用痛苦地重写全局require函数,而且不会出现任何问题。 它可以帮助您将应用程序组织为松散耦合的模块。
但是我很难找到一个我和我的团队可以轻松采用的依赖注入框架。所以我最近基于这些特性构建了一个名为deppie的框架
可以在几分钟内学会的最小API 不需要额外的代码/配置/注释 一对一直接映射需要的模块 可以部分地使用现有代码吗
TypeDI是这里提到的最可爱的,看看TypeDI中的代码
import "reflect-metadata";
import {Service, Container} from "typedi";
@Service()
class SomeClass {
someMethod() {
}
}
let someClass = Container.get(SomeClass);
someClass.someMethod();
看看这段代码:
import {Container, Service, Inject} from "typedi";
// somewhere in your global app parameters
Container.set("authorization-token", "RVT9rVjSVN");
@Service()
class UserRepository {
@Inject("authorization-token")
authorizationToken: string;
}
看看dips(一个简单而强大的Node.js依赖注入和实体(文件)管理框架)
https://github.com/devcrust/node-dips
我一直很喜欢IoC的简单理念——“你不需要了解任何环境,需要的时候有人会叫你。”
但是我看到的所有IoC实现都完全相反——它们用更多的东西使代码变得混乱。所以,我创建了我自己的IoC,就像我想要的那样-它保持隐藏和不可见的90%的时间。
它用于MonoJS web框架http://monojs.org
我说的是简单的事情,比如共享一个数据库连接对象 但我还没有找到一个让我满意的解决办法。
它是这样做的——在配置中注册组件一次。
app.register 'db', ->
require('mongodb').connect config.dbPath
可以在任何地方使用
app.db.findSomething()
你可以在https://github.com/sinizinairina/mono/blob/master/mono.coffee这里看到完整的组件定义代码(包括DB Connection和其他组件)
这是你必须告诉IoC该做什么的唯一地方,之后所有这些组件都将自动创建和连接,你不再需要在应用程序中看到IoC特定的代码。
国际奥委会本身https://github.com/alexeypetrushin/miconjs