我知道通常注入器应该在所有应用程序中只使用一次(在启动时)。但我有以下用例。我为 Executor 注入任务实现,然后在该任务中我有依赖项(比如说FileHandler
),每次都必须实例化。FileHandlerProvider
我知道方法是注入每次请求时都会返回新实例的提供程序(比如说)。问题是FileHandler
它自己有很多依赖项(比如说Parser
,OutputPrinter
...)。现在那些也每次都需要新的实例(因为实现可能有一些状态,例如计数器,并且在下一个线程运行时重用相同的实例将是一个问题)。问题是在注入提供者之后,提供者的相同实例被重用,所以新FileHandler
的总是用相同的Parser
和OuputPrinter
. 解决方案可能是再次注入ParserProvider
andOutputPrinterProvider
而不是 Parser 和OuputPrinter
in FileHandlerProvider
,但这并不正确,它很快就会变得太复杂,因为有更多的依赖关系。我现在看到的唯一简单的解决方案可能是使用 Injector in FileHandlerProvider
,这将返回新实例FileHandler
(和依赖项的新实例)。或者在这种情况下可能还有另一种更优雅的解决方案?
问问题
2238 次
1 回答
4
您应该只使用默认范围(即无范围)绑定FileHandler
及其依赖项。然后在每次需要新实例时注入Provider<FileHandler>
并使用它。由于没有范围,因此每次都称为需要创建的新实例......并且由于其依赖项也没有范围,因此每次也需要创建它们中的每一个的新实例。它应该按照您想要的方式工作。get()
FileHandler
FileHandler
get()
FileHandler
我认为您(可能)在这里缺少的事情是您不需要自己编写任何这些提供程序……只需注入Provider<FileHandler>
,Guice 就会为您完成所有工作。
编辑:这是我编写的一个小类,它演示了每次创建该类的实例时都会创建新的类的依赖关系。
public class Test {
public static void main(String[] args) {
Injector injector = Guice.createInjector();
injector.getInstance(Test.class);
}
@Inject public Test(Provider<FileHandler> fileHandlerProvider) {
FileHandler fileHandler1 = fileHandlerProvider.get();
FileHandler fileHandler2 = fileHandlerProvider.get();
System.out.println("fileHandler1 == fileHandler2? " +
(fileHandler1 == fileHandler2));
System.out.println("fileHandler1.parser == fileHandler2.parser? " +
(fileHandler1.parser == fileHandler2.parser));
System.out.println("fileHandler1.print == fileHandler2.printer? " +
(fileHandler1.printer == fileHandler2.printer));
}
private static class FileHandler {
private final Parser parser;
private final OutputPrinter printer;
@Inject private FileHandler(Parser parser, OutputPrinter printer) {
this.parser = parser;
this.printer = printer;
}
}
private static class Parser {
}
private static class OutputPrinter {
}
}
运行时,此代码打印:
文件处理程序1 == 文件处理程序2?错误的 fileHandler1.parser == fileHandler2.parser?错误的 fileHandler1.print == fileHandler2.printer?错误的
这表明不仅FileHandler
每次都会创建一个新实例,而且每次都会创建新Parser
实例OutputPrinter
并将其注入FileHandler
。
于 2011-01-22T20:15:28.267 回答