Guice guidance on side-effects in modules基本上是"不做。"与执行I/O in Providers相同,我假设包含模块。然后,他们给出了一个使用Service接口的空白示例,该接口以正确的顺序启动其服务。
Injector injector = Guice.createInjector(
new DatabaseModule(),
new WebserverModule(),
...
);
Service databaseConnectionPool = injector.getInstance(
Key.get(Service.class, DatabaseService.class));
databaseConnectionPool.start();
addShutdownHook(databaseConnectionPool);
Service webserver = injector.getInstance(
Key.get(Service.class, WebserverService.class));
webserver.start();
addShutdownHook(webserver);
但在现实世界中,网络服务器传递依赖于数据库。而且,获得DataSource的唯一方法是连接到数据库。在Web服务器和数据库之间有几层抽象,都希望注入依赖项并开始服务。
我考虑过两种不同的选择来处理这种情况。首先是使用guice的服务,但注入Provider<DataSource>
或等价物。但这会在我的代码中泄露,因为现在所有内容都使用Provider<LayerBelow>
而不是实际的LayerBelow
我尝试的第二种方法是链接创建注入器,我在每层构建一个子注入器,启动该层,然后使用它为下一个创建子注入器。它似乎也很笨拙。像这样:
// I/O in the static method call; returns a module with
// the environment-based objects
EnvironmentModule environment = EnvironmentModule.configureEnvironment(args);
Injector injector = Guice.createInjector(
environment,
// the following connects to the database, and returns a module
// providing the DataSource
SQLModule.connectToDatabase());
injector = injector.createChildInjector(new BusinessLayerModule());
startTimers(injector);
injector = injector.createChildInjector(
new ServicesModule(),
new WebServerModule());
startServer(injector);
启动时是否有更好的方法来执行I / O和副作用?我使用的是Guice 4
相关问题:
答案 0 :(得分:0)
我的方法类似于你的第二种方法,除了儿童注射器。
首先,创建一个专用于初始化的模块SQLModule:
Injector initInjector = Guice.createInjector(Stage.PRODUCTION, new SQLModule());
SQLService service = initInjector.getInstance(SQLService.class);
Properties initProps = service.doInit(); // for example
然后创建主模块:
Injector mainInjector = Guice.createInjector(Stage.PRODUCTION,
new SQLModule(),
new MainModule(initProps));
// main program here using the mainInjector
答案 1 :(得分:0)
例如,我有两个模块,主要用于整个应用程序&#34; fat&#34;非常早期注入,BasicConfigurationService
非常早期注入;),Basic没有SQL连接等。目标是解析SQL连接和最常用的应用程序数据路径。
模块定义以这种方式设置,当main
激活时,basic
已经激活/注入。
对不起,如果我的英文不太清楚。