Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global injectors with Guice

I'm creating a library and to help with ergonomics, I'm passing the injector created at application startup to different components in the library so that users can do getInstance() from within certain contexts without having to pre-plan where to stick their @Inject annotations.

Here's an example of the API design:

public static void main(String[] args) {
  // Main injector is created here behind the scenes. 
  ApexApplication app = new ApexApplication()

  app.get("/users/:id", context -> {
    // Users can do this instead of @Inject UserDAO dao
    UserDAO dao = context.getInstance(UserDao.class)
    User user = dao.findUserById(context.param("id"))
    //... 
  })
  app.start();
}

Here are links to the key implementation details for clarity:

  • #1: Here is where I create the initial (and only) injector
  • #2: I then pass it along to another library component as part of its constructor
  • #3: The other component then delegates calls to getInstance() to the original injector

I know that the best practice wrt Guice injectors is to create one and only one throughout the application, use it to inject all dependencies, then throw it away; However, given what I am trying to achieve, would this approach be recommended or is there another pattern I should look into?

like image 314
kshep92 Avatar asked Feb 03 '26 11:02

kshep92


1 Answers

I do not think that it is a good idea to send the context with injector to every other class in order to have the access to the injector.

There is another approach, actually pretty similar to the idea of MyModuleHelper of @Jameson. The DIContainer does static initialization of the injector and provides the public static API getInjector(). This way you can have the injector, which is created only once and it is available to whatever class without boilerplate code:

public final class DIContainer {
     private static final Injector injector;
     static {
         injector = Guice.createInjector(new AppModule());
     } 
     public static Injector getInjector() {
         return injector;
     }
     private DIContainer() {
     }
}

Usage example:

ServiceProvider service = DIContainer.getInjector().getInstance(ServiceProvider.class);

May be this post is useful as well.

like image 50
asch Avatar answered Feb 06 '26 02:02

asch