Running inside Guice injector, @Injects not respected on `new`
We have a Swing-application we would like to add a slight touch of dependency injection to using Guice-3.0. Our reason is to migrate our old Factories into something more flexible.
I have ensured that the application runs inside an injector, and we now want to have a class way down have some fields @Inject'ed, and it appears to my untrained eye that the @Inject annotations on this class is ignored when the "new" is running.
Question now is if I have understood correctly that classes being new'ed when first running inside a Guice injector are guaranteed to have their @Inject annotations respected, or if this property is lost after one or more new's in your code.
In other words:
Given A gets an instance of B from Guice, and B then creates new C()
which in turn runs new D()
, and D happen to have @Inject's inside, should D be processed by Guice?
If yes, how can I add code to my Guice configuration that allows me to see that "new X()" is being processed by Guice and that "@Inject setY(Y y)" is being executed? I do not mind if this log will be very large - I just need to verify that Guice is working as I expect it to.
No, nothing created with new
directly is handled by Guice... it doesn't do magic. The way Guice is supposed to work is that it creates your object graphs for you. You aren't supposed to reference the Injector
within your classes and you aren't supposed to use new
to create services that you want injected.
Here are some options you might have:
C
into B
rather than new
ing it. Inject D
into C
. new
ing them in, inject Provider<C>
or Provider<D>
instead and use get()
rather than new
. CFactory
or DFactory
instead of a Provider
. injector.injectMembers(Object)
to inject objects you've created with new
... but it's hard to say if Guice is helping you much if you're doing that. As ColinD pointed out, in your example D would not be created by Guice. Calling new on an Object will construct it outside of a the Guice DI. If you want to confirm that something is being created through Guice, you could add logging to the @Inject setter methods or if you're doing constructor injection, you could add a new method just for logging purposes:
@Inject
public void log() {
logger.debug(//check if injected classes have been set)
...
}
Having converted a large, Swing application to use Guice, and written a new one from the ground up there are some things to keep in mind.
1) Guice was not designed for desktop applications. It was created for use on Servers. Startup time is not something that was taken into consideration. After fully converting a Swing application from all static factories to all Guice, it added ~30/60 seconds onto the startup time depending on if it was a cold or warm startup.
2) It's very difficult to add only some Guice. As you're now discovering you'll quickly want a dependency on a constructed class three levels deep and either have to convert it all to Guice or start passing lots of classes through constructors and add getters
3) Beware of eagerly creating objects with Guice. @Singleton by default eagerly constructs the object at startup. This can be disastrous to startup time of the app. If you're worried about this there's a nice thread on the Guice forum about creating a @EagerSingleton or @LazySingleton to might want to check out
4) with all that being said, Guice is pretty awesome, just have to be aware of how its working to get good performance with it in a desktop app
链接地址: http://www.djcxy.com/p/94646.html上一篇: 使用guice创建类的多个实例