We have been asked to explore guice as a dependency injection framework as it's light weight. I'm learning/experimenting with guice and have a few questions I couldn't understand so thought I'd ask.
1) When does guice make the dependencies available? During the execution of the line Guice.createInjector ajf then reads the module and constructs the entire object graph? Or does it inject when the very first time an object is constructed or a method called?
2) Are Providers the only way to lazy instantiate the classes in guice?
3) Finally, let's say I have a module A
and module B
assembled together to create a war. The guice dependencies of A are in it's own guice module and so is B's. A
has a maven dependency on B
for a few classes.
I know for a fact that a specific class in B
will never be needed to be injected by guice as it'll not going to be called at all in A
and I don't give it a binding. However guice tells me that I don't have a binding for the class in B
and throws ProvisionException. When I know for a feature I'm running the app for will not need a class to be injected how do I tell guice to ignore them or not care about them until it's needed?
In order:
When does guice make the dependencies available?
In general, construction is lazy (for non-singleton classes, this is intuitive - you don't know you need a new instance until someone tells you to inject one somewhere). The exception is for eager singletons which are constructed (wait for it) eagerly. The documentation on Scopes has more information about making your Singletons eager or not.
Are Providers the only way to lazy instantiate the classes in guice?
No, the @Inject
annotation or a manual call to an Injector
instance are also lazy. Singleton providers are the only way to get eager instantiation.
When I know for a feature I'm running the app for will not need a class to be injected how do I tell guice to ignore them or not care about them until it's needed?
I looked around but couldn't find an answer to this, other than the easy one I thought of initially: stub a useless provider. It's not clean, but I don't see a clean way around this issue, if you can't change B
.
More broadly, I'm curious what the owners of B
did to cause this error, and whether it was "worth it". I like keeping injection logic only in my Guice modules and static (main()
) methods. That way, my classes can be used by anyone, regardless of whether they too use Guice or a different framework.
UPDATE:
You may be able to work around #3 by using the DEVELOPMENT
stage, which will avoid checking up-front that injections are all provided. However, this is probably not a good idea - it would be cleaner to run in PRODUCTION
and take the hit of writing a useless provider.
There's also one last approach you may or may not want to try: are you currently installing B
's module on your injector, in order to get the classes you need from B
? If so, you could consider not installing B
's module, and instead adding the required providers to a module of your own, leaving out any you don't need (i.e. the problematic one). I can't promise this will solve your problem, though, without seeing your code :)