Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injector Hierarchy / Child Injector explanation?

Tags:

java

guice

I have been looking over the net for an explanation about the injector heirarchy and how/when to use createChildInjector(), but I cannot find a clear and concise explanation.

Here is my use case:

  • I have a base application module which I use to inject certain context items. This module should be included in every injector instance.
  • I have a search module which searches a database
  • I have a search module which searches ElasticSearch. Some of the bindings in this class should override the bindings that are provided in the database search module.

For example, say the database search module contains:

bind(PlaceSearch.class).to(HibernatePlaceSearch.class);
bind(PersonSearch.class).to(HibernatePersonSearch.class);

And the ElasticSearch module contains:

bind(PersonSearch.class).to(PersonElasticSearch.class); 

Is there a way to create an injector that includes the PlaceSearch binding from the database search module and the PersonSearch binding from the ElasticSearch module without creating a separate module that contains

bind(PlaceSearch.class).to(HibernatePlaceSearch.class);
bind(PersonSearch.class).to(PersonElasticSearch.class);

? Is this a case for Modules.override()? A case for createChildInjector? Thanks ahead of time!

like image 405
jcampos8782 Avatar asked Aug 31 '13 17:08

jcampos8782


People also ask

What is hierarchical injector?

Hierarchical dependency injection enables you to share dependencies between different parts of the application only when and if you need to.

What are the two types of injector hierarchies we have?

You can configure providers for different injectors in the injector hierarchy. An internal platform-level injector is shared by all running apps. The AppModule injector is the root of an app-wide injector hierarchy, and within an NgModule, directive-level injectors follow the structure of the component hierarchy.

What does injector getInstance do?

getInstance. Returns the appropriate instance for the given injection type; equivalent to getProvider(type). get() . When feasible, avoid using this method, in favor of having Guice inject your dependencies ahead of time.


2 Answers

The Modules.override() is not working in Stage.PRODUCTION. You should use PrivateModule where the binding is valid/visible only inside private module, so you can bind different implementation classes to the same interface. Then you can install the Private module to the parent Module, but you have to explicitly expose() all binding you want to make visible for other modules.

Guice - Private Modules

Lets say:

DatabaseSearchModule.java (extends PrivateModule)

bind(PlaceSearch.class).annotatedWith(Names.named("dbSearch")).to(HibernatePlaceSearch.class);
bind(PersonSearch.class).to(HibernatePersonSearch.class);
expose(PlaceSearch.class).annotatedWith(Names.named("dbSearch"));

EleasticSearchModule.java (extends PrivateModule)

bind(PersonSearch.class).annotatedWith(Names.named("elastic")).to(PersonElasticSearch.class);
expose(PersonSearch.class).annotatedWith(Names.named("elastic"));

Well then you can install it in some Parent abstract or servlet module

MainModule.java

install(new DatabaseSearchModule());
install(new EleasticSearchModule());

bind(OtherClass.class);

OtherClass.java

@Inject @Named("elastic")
private PlaceSearch elasticSearch;
@Inject @Named("dbSearch")
private PlaceSearch dbSearch;

You can use Named annotation or you can create very elegant own binding Annotation.

like image 68
Milan Baran Avatar answered Oct 05 '22 14:10

Milan Baran


This is a perfect case for Modules.override().

Most applications shouldn't use child injectors. They add a lot of configuration complexity and have some surprising behavior for corner cases.

like image 38
Jesse Wilson Avatar answered Oct 05 '22 13:10

Jesse Wilson