So, some of the Dagger/Guice folks at Google created a thing called AutoFactory (http://github.com/google/auto) in a project that includes AutoFactory (code-generated assisted injection), AutoValue (code-generated custom value types) and AutoService (auto-generation of java services metadata files).
AutoFactory pretty much operates like you would expect - it generates the factory you would otherwise have hand-rolled. It's a very early version, and we have a lot more flexibility planned, but it will generate a factory class that will take a type that includes some JSR-330 injectable dependencies and some call-stack parameters, and merge them together in creating instances of the annotated type.
In essence it will generate the factory you wrote, automatically if you properly annotate your factory-created type.
For instance, if you create your class:
@AutoFactory
public class ImageDownloader {
// Get these dependencies from the injector.
private final HttpClient httpClient;
private final ExecutorService executorService;
// Get these from the caller.
private final URL imageUrl;
private final ImageCallback callback;
ImageDownloader(
@Provided HttpClient httpClient,
@Provided ExecutorService executorService,
ImageCallback callback,
URL imageUrl) {
// assignments
}
}
AutoFactory will generate:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public final class ImageDownloaderFactory {
private final Provider<ExampleClasses.HttpClient> httpClientProvider;
private final Provider<java.util.concurrent.ExecutorService> executorServiceProvider;
@Inject
public ImageDownloaderFactory(
Provider<ExampleClasses.HttpClient> httpClientProvider,
Provider<java.util.concurrent.ExecutorService> executorServiceProvider) {
this.httpClientProvider = httpClientProvider;
this.executorServiceProvider = executorServiceProvider;
}
public ImageDownloader create(ImageCallback callback, URL imageUrl) {
return new ImageDownloader(
httpClientProvider.get(),
executorServiceProvider.get(),
callback,
imageUrl);
}
}
(Note, we have a bunch of clean-up to do on the output source, but the above is basically what is generated, though not quite as nicely formatted.)
The resulting class is then, properly a JSR-330 compliant injectable class, which you can inject in your dependency graph (in Dagger or Guice) and it will create these objects for you, co-mingling the call-stack state with the provided dependencies appropriately.
You can inject the above Just-In-Time, or you can provide it via an @Provides
method at your leisure.
You can even have the factory implement a factory interface, and then simply bind the two together in a dagger module like so:
@AutoFactory(implementing = MyFactoryInterface.class)
public class ImageDownloader {
// ... otherwise as above...
}
@Module(...)
class MyModule {
@Provides MyFactoryInterface factoryImpl(ImageDownloaderFactory impl) {
return impl;
}
}