InversifyJS:每个HTTP请求的依赖实例化

时间:2017-07-28 17:07:48

标签: express typescript dependency-injection inversifyjs

我在Express项目中使用Inversify.JS。我想创建一个与Neo4J数据库的连接,这个过程有两个对象:

  1. 驱动程序对象 - 可以在整个应用程序中共享并仅创建一次
  2. 会话对象 - 每个HTTP请求都应该创建一个针对驱动程序的会话,其生命周期与http请求生命周期相同(只要请求结束,连接就被销毁)
  3. 如果没有Insersify.JS,可以使用简单的算法解决此问题:

    exports.getSession = function (context) { // 'context' is the http request 
      if(context.neo4jSession) {
        return context.neo4jSession;
      }
      else {
        context.neo4jSession = driver.session();
        return context.neo4jSession;
      }
    };
    

    (例如:https://github.com/neo4j-examples/neo4j-movies-template/blob/master/api/neo4j/dbUtils.js#L13-L21

    要为驱动程序创建静态依赖项,我可以注入一个常量:

    container.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver());

    如何创建仅为每个请求实例化的依赖项并从容器中检索它们?

    我怀疑我必须在像这样的中间件上调用容器:

    this._express.use((request, response, next) => {
        // get the container and create an instance of the Neo4JSession for the request lifecycle
        next();
    });
    

    提前致谢。

1 个答案:

答案 0 :(得分:0)

我看到了两个问题的解决方案。

  1. inRequestScope()用于DbDriver依赖项。 (自4.5.0版本起可用)。如果您对一个http请求使用单个组合根,它将起作用。换句话说,每个http请求只调用container.get()一次。
  2. 创建子容器,将其附加到response.locals._container并将DbDriver注册为单身。

    let appContainer = new Container()
    appContainer.bind(SomeDependencySymbol).to(SomeDependencyImpl);
    
    function injectContainerMiddleware(request, response, next) {
         let requestContainer = appContainer.createChildContainer();   
         requestContainer.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver());
         response.locals._container = requestContainer;
         next();
    }
    
    express.use(injectContainerMiddleware); //insert injectContainerMiddleware before any other request handler functions
    
  3. 在此示例中,您可以在DbDriver之后注册的任何请求处理程序/中间件函数中从response.locals._container检索injectContainerMiddleware,您将获得DbDriver的相同实例

    这会有效,但我不确定它的表现如何。另外我想在http请求完成后你可能需要以某种方式处理requestContainer(取消绑定所有依赖项并删除对父容器的引用)。