Search code examples
javadependency-injectiondagger-2

Seeding Dagger 2 Factory with Config


I'm just getting started with Dagger & Dependency Injection and wondering about configuration at runtime for some of the lower-level dependencies. Is there a way to provide a low-level injected Singleton with a configuration object at runtime?

Basic idea of what I'm after:

@Singleton
class DatabaseService {
   @Inject
   public DatabaseService(DatabaseConnectionConfig config) { // how can this arg be passed in at runtime?
      // make the connection
   }
}

@Singleton
class HighLevelService {
   @Inject
   public HighLevelService(DatabaseService db) {
   }
}

@Module
class Module {
  @Binds
  abstract HighLevelService bindHighLevelService(HighLevelService svc);

  @Binds
  abstract DatabaseService bindDatabaseService(DatabaseService svc);
}


@Singleton
@Component(modules = {
    Module.class
})
interface Factory {
  HighLevelService highLevelService();

  static Factory create() {
    return DaggerFactory.create();
  }
}

public class App {
  public static void main(String[] args) {
    // get the config details from the arguments
    DatabaseConnectionConfig config = parseDBConfigFromArgs(args);
    // is there a way to configure the DatabaseConnectionConfig from here?
    HighLevelService svc = Factory.create().highLevelService();
  }
}

Solution

  • You can use a @Component.Factory (or @Component.Builder) with @BindsInstance.

    @Singleton
    @Component
    interface Factory {
        HighLevelService highLevelService();
    
        // This nested interface is typically called "Factory", but I
        // don't want to look up how to access Factory from Factory.Factory
        @Component.Factory
        interface MyFactory {
            Factory create(@BindsInstance DatabaseConnectionConfig config);
        }
    
        static Factory create(DatabaseConnectionConfig config) {
            return DaggerFactory.factory().create(config);
        }
    }
    
    public class App {
      public static void main(String[] args) {
        DatabaseConnectionConfig config = parseDBConfigFromArgs(args);
    
        HighLevelService svc = Factory.create(config).highLevelService();
      }
    }