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 开发者_JAVA技巧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:
- Inject
C
intoB
rather thannew
ing it. InjectD
intoC
. - If you need to create either or both of these multiple times within the class you're currently
new
ing them in, injectProvider<C>
orProvider<D>
instead and useget()
rather thannew
. - If there are objects only available at runtime that need to be passed to these classes (something based on user input or data from elsewhere, say) to create them, you may need to use Assisted Inject and inject a
CFactory
orDFactory
instead of aProvider
. - If you really can't find any better way, you can use
injector.injectMembers(Object)
to inject objects you've created withnew
... 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
精彩评论