I know that generally injector should be used only once in all application (on startup). But i have following use case. I inject task implementation for Executor, and then inside that task i have dependency (lets say FileHandler
) that has to be instantiated each time. I know the way is to inject provider (lets say FileHandlerProvider
) that will return new instance each time requested. The problem is that FileHandler
has a lot of dependencies of it own (lets say Parser
, OutputPrinter
...). Now those also need new instance each tim开发者_StackOverflow社区e (because implementations could have some state, for example counters, and on next thread run reusing same instance would be a problem). The thing is that after provider is injected the same instance of provider is reused, so new FileHandler
is always created with same Parser
and OuputPrinter
. The solution could be again to inject ParserProvider
and OutputPrinterProvider
instead of Parser and OuputPrinter
in FileHandlerProvider
, but thats just not right, it gets too complicated soon, because there are more dependencies. The only simple solution I see now could be to use Injector in FileHandlerProvider
, that would return new instance FileHandler
(and new instances of dependencies). Or maybe there is another more elegant solution in this situation?
You should just bind FileHandler
and its dependencies all with default scope (i.e. no scope). Then inject Provider<FileHandler>
and use its get()
every time you need a new FileHandler
instance. Since FileHandler
has no scope, each time get()
is called a new instance of FileHandler
needs to be created... and since its dependencies also have no scope, a new instance of each of them needs to be created each time as well. It should work just the way you want.
I think the thing that you're (maybe) missing here is that you don't need to write any of these providers yourself... just inject Provider<FileHandler>
and Guice will do it all for you.
Edit: Here's a small class I wrote that demonstrates the dependencies of a class getting created new each time an instance of that class is created.
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 {
}
}
When run, this code prints:
fileHandler1 == fileHandler2? false fileHandler1.parser == fileHandler2.parser? false fileHandler1.print == fileHandler2.printer? false
This shows that not only was a new FileHandler
instance created each time, new Parser
and OutputPrinter
instances were create and injected in to the FileHandler
each time as well.
精彩评论