Reputation: 17898
So I am trying to extend guice with some annotations on my own pretty much following the great article I found here: http://developer.vz.net/2012/02/08/extending-guice-2/
This works quite OK for me except the thing:
Now in my module I instantiate one of these services:
final SchedulerService schedulerService = new SchedulerService();
And here is the hidden evil. This guy was lucky enough he needed just simple object without any dependencies. But in my case my Service
needs reference to two more sub-services. And since he used new
to create the Service
I need to use new
for both the two subservices so I'll be able to create it. So I can't inject some properties into these subservices. Effectively I'm creating whole object-subtree which is not guicified.
Is there a way around it? Can I maybe let Guice to instantiate the Service
for me and then register it in TypeListener
?
Upvotes: 0
Views: 279
Reputation: 95764
You can actually get access to providers of injected items from within a module using getProvider
(on Binder and AbstractModule), as long as you promise not to call get
until after the Injector exists. (You'll get an IllegalStateException if you do.)
At that point your code looks something like this:
Provider<YourService> yourServiceProvider = getProvider(YourService.class);
final InjectionListener injectionListener = new InjectionListener() {
public void afterInjection(Object injectee) {
yourServiceProvider().get().accept(injectee);
}
}
The only problem here is that injecting your service and its dependencies will probably also try to trigger your InjectionListener, likely causing an infinite loop. You could solve that by adding a null guard and ignoring all injections while your service is null. Your better bet, though, might be to create an injector without the listener to bootstrap YourService, and add the listener into a child injector:
Injector injectorWithoutListener = Guice.createInjector(new YourServiceModule());
YourService yourService = injectorWithoutListener.getInstance(YourService.class);
Injector finalInjector = injectorWithoutListener.createChildInjector(
new YourInjectionListenerModule(yourService), new EverythingElseModule());
Note that objects with singleton behavior configured in the parent injector will still be created there, so instances created in the finalInjector
will share singleton behavior with the instances in injectorWithoutListener
. You can also read more about createChildInjector and binding resolution order.
Upvotes: 2