I have a Guice based project using vanilla Guice;
no Assisted-Inject, no AOP, no extra plugin extending Guice, etc.
To run it more easily on Android, Dagger seems like a better solution.
Every class has a dependency and a constructor with #Inject annotation.
No field or method injection is used.
The modules are quite simple (making Guice an overkill) and mostly contain bindings like the following:
class SomethingModule extends AbstractModule {
protected void configure() {
Bind(Handler.class)
.annotatedWith(Names.named("something"))
.to(SomeImplementation.class);
}
}
}
And later used like the following:
Injector inj = Guice.createInjector(new SomethingModule());
... = inj.getInstance(SampleInterface.class);
// and rest of the code.
Unfortunately,
I can not get my head around Daggers terminology.
Can you guide me with a direct translation / transformation of a Guice module to a Dagger module?
Dagger has:
Dagger's Components.
Dagger's Modules.
#Provides
#Inject
Guice has:
#Inject
#Named (or any custom annotation, if implemented correctly).
Our modules extending AbstractModule.
#Provides in the modules.
Guice Injector created from modules.
How do these relate?
Update: In addition to the nice answer by EpicPandaForce, these slides can help too.
Bind(Handler.class)
.annotatedWith(Names.named("something"))
.to(SomeImplementation.class);
Would translate to
#Module
public class SomethingModule {
#Provides
#Named("something")
//scope if needed
public Handler handler() {
return new SomeImplementation();
}
}
Which would be bound to an "Injector" (component):
#Component(modules={SomethingModule.class})
//scope if needed
public interface SomethingComponent {
#Named("something")
Handler handler();
void inject(ThatThingy thatThingy);
}
Which is an "injector" that you have to create with the APT-generated builder:
SomethingComponent somethingComponent = DaggerSomethingComponent.builder()
.somethingModule(new SomethingModule()) //can be omitted, has no params
.build();
somethingComponent.inject(thatThingy);
Where that thingy has
public class ThatThingy {
#Inject
#Named("something")
Handler handler;
}
Components typically exist per scope, so for example #ApplicationScope has one "injector" (component). Scoping can be achieved with subcomponents and component dependencies.
Important fact, a component has provision methods (which are the dependencies that are inherited to subscoped components if you use component dependencies), and void inject(X x); formatted methods. This is required for field injection per concrete type. A base class for example can only inject itself, and not its subclasses. You can however write a method called protected abstract void injectThis() which would call the .inject(this) on the subclass as well.
As I haven't really used Guice, I'm not sure if I missed out on anything. I think I forgot constructor injection, which is an issue because while Dagger does support it, it cannot be reconfigured. For reconfiguration, you have to use modules, and do the injection in the constructors yourself.
#Module(includes={ThoseModule.class, TheseModule.class})
public abstract class SomethingModule {
#Binds
abstract Whatever whatever(WhateverImpl impl);
}
#Singleton
public class WhateverImpl implements Whatever {
Those those;
These these;
#Inject
public Whatever(Those those, These these) {
this.those = those;
this.these = these;
}
}
#Component(modules={SomethingModule.class})
#Singleton
public interface SomethingComponent {
These these();
Those those();
Whatever whatever();
}
Related
Suppose I'm building a car and I have several Brake beans with different implementations
class Car {
#Inject
Car(#BrakeType(value="abs")Brake frontBrake, #BrakeType(value="nonabs")Brake rearBrake) { }
}
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
public #interface BrakeType {
String value();
}
interface Brake {}
#BrakeType(value="abs")
class AbsBrakeImpl implements Brake {
#Inject AbsBrakeImpl() {}
}
#BrakeType(value="nonabs")
class BrakeImpl implements Brake {
#Inject BrakeImpl() {}
}
why does my CarModule have to define #Provides for the specific Brake types? Shouldn't the custom annotation type #BrakeType be enough to determine which impl to inject? Or would that require using reflection, which dagger2 does not use?
#Module
public class CarModule {
#Provides #BrakeType("abs")
public Brake absBrake() {
return new AbsBrakeImpl();
}
#Provides #BrakeType("nonabs")
public Brake nonabsBrake() {
return new BrakeImpl();
}
}
Dagger doesn't look at qualifier annotations on classes, only on #Provides or #Binds methods. So the #BrakeType(value="abs") annotations on your classes don't have any effect.
A more canonical way of writing your code is:
class AbsBrakeImpl implements Brake {
#Inject AbsBrakeImpl() {}
}
class BrakeImpl implements Brake {
#Inject BrakeImpl() {}
}
#Module
abstract class CarModule {
#Binds #BrakeType("abs")
abstract Brake absBrake(AbsBrakeImpl impl);
#Binds #BrakeType("nonabs")
abstract Brake nonabsBrake(BrakeImpl impl);
}
Note that since you have #Inject on the constructors of your implementations, you can simply use Dagger's #Bind to bind the implementations directly to the appropriately qualified interface.
Reflection is probably not a big issue here because it would happen at compile time.
I did not look through the source code, but dagger is but an annotation processor—it registers to be called whenever a set of given annotations is used. While the qualifier alone would probably be enough to find out what you intended, I can think of the following reasons why this could not be the best solution.
javax.inject.Qualifier is part of a bigger API, and might also be used by other libraries in different context. So you might not want dagger to generate code for a method, just because it is annotated with a qualifier.
Another reason could be that since there is the possibility to create custom qualifiers, dagger would have to check every annotation on every method in every module and then in turn determine whether that annotation itself is annotated with #Qualifier to see if the method is of some interest to it. This is rather an unnecessary overhead.
There might be more reasons, but those 2 listed here seem enough to just make users of dagger use some sort of contract: #Provides.
Annotations don't affect the performance of the code, and having an addtional annotation won't do any harm, so there is more to gain than to lose by handling it the way they do.
For the record, you can use your own qualifier annotations (as BrakeType), or just use #Named from Dagger.
Using this last one, your code will look something like:
#Inject #Named("abs") Brake frontBrake;
#Inject #Named("nonabs") Brake rearBrake;
And on your module:
#Provides #Named("abs") static Brake provideAbsBrake() {
return new AbsBrakeImpl();
}
#Provides #Named("nonabs") static Brake provideNonAbsBrake() {
return new BrakeImpl();
}
Remember to use Dagger name conventions (like provide prefix) to get most of it. And on your modules try to use all #Provides methods static, doing so the resultant implementation does not need to instantiate it.
In short, Provides and Qualifiers work together so you need both.
Source: Dagger users guide.
#Inject constructor means provide a type that class itself, in your case, which mean you provide the AbsBrakeImpl type and BrakeImpl type, so when you try to inject with Brake, dagger can not found the provider.
Qualifier in #Inject constructor is not work, because class type is unique, we don't need to add a qualifier to.
So, in your case, or you have to use CarModule to tell Dagger explicitly, or change your constructor with
class Car {
#Inject
Car(AbsBrakeImpl frontBrake, BrakeImpl rearBrake) { }
}
I'm working with a Guice enabled framework.
When using classes that were created by the framework (or subclasses that override existing bindings), I can instantiate framework provided variables very easily. Whatever I need, it's just a matter of
#Inject
FrameworkProvidedType variable;
However, in my custom created classes, that doesn't work. All of the injected variables are null.
It's my understanding that in order to use injection, my class has to have a binding.
If I'm subclassing an existing framework class, I can override the binding in my module class. That's pretty straightforward.
But I have a new class and I don't know how to bind it to the underlying framework.
public Class myCustomClass {
private String iNeedthis;
private Context thisToo;
#Inject
FrameWorkThing magic;
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
public void DoMagic(){
//null pointer error because magic was not injected
magic.doMagic(this.iNeedthis);
}
}
How do I Guice-enable this new class?
I tried this in my Runtime Module
public Class<myCustomClass> bindMyCustomClass(){
return MyCustomClass.class;
}
and failed miserably.
No thanks to #bmorris591 who dismissed and downvoted the question out of the gate, I found an answer.
#Inject-ing a field into a class means that the class instance needs to be created by Guice.
Step 1 is creating a factory for the class. This may not be necessary, but it worked for me.
public interface MyCustomClassFactory {
public MyCustomClass create(String iNeedThis, Context thisToo);
}
Step 2 is installing the factory into Guice
#Override
public void configure(Binder binder) {
super.configure(binder);
binder.install(new FactoryModuleBuilder().build(MyCustomClass.class));
}
In my particular case - the framework I'm working with provides a Module class that is an implementation of com.google.inject.Module.
Within that class is a "configure(Binder binder)" function that is called on startup.
Step 3 is actually annotating the constructor
#Inject
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
Useful and related web page that put me on the right track:
http://beust.com/weblog/2012/08/21/advanced-dependency-injection-with-guice/
This talks about assisted injection, but it gave enough information and a simple enough to understand example that taking the next step was pretty easy.
Lot's of times, classes need to be instantiated (constructed), and then "wired" (configured) before they can be used. For instance:
// Construction.
EventBus bus = new EventBus();
FizzEventHandler fizzHandler = new FizzHandler();
BuzzEventHandler buzzHandler = new BuzzHandler();
// Wiring.
bus.register(fizzHandler);
bus.register(buzzHandler);
In Guice, we accomplish the first part (construction; injection) with a Binder:
public class MyModule extends AbstractModule {
#Override
public void configure() {
bind(EventBus.class).to(SimpleEventBus.class);
bind(FizzEventHandler.class).to(DefaultFizzEventHandler.class);
bind(BuzzEventHandler.class).to(DefaultBuzzEventHandler.class);
}
}
But where does the wiring take place? When my Guice-based app starts up, we engage the DI "bootstrapping" process:
public class MyApp {
private EventBus bus;
private FizzEventHandler fizzHandler;
// ...etc.
public static void main(String[] args) {
MyApp app = new MyApp();
app.run();
}
public MyApp() {
// Bootstrap DI.
MyModule myModule = new MyModule();
Injector injector = Guice.createInjector(myModule);
bus = injector.inject(EventBus.class);
fizzHandler = injector.inject(FizzEventHandler.class);
// ...etc.
// Wire
bus.register(fizzHandler);
}
}
This works OK for the top-level (root) DI classes. But as we get further "down" the dependency tree, and get into all the other objects used by the application, putting the wiring logic in constructors like this is ugly and (I believe) is a discouraged practice.
So I ask: where doe battle-weary Guice veterans place their wiring/config code?
I work on a reasonably big system (~3000 classes) which uses Guice. I would say that our approach is to do everything with constructors. There aren't distinct "construction" and "wiring" activities as you describe, there's only construction.
In your example, the event handlers would be constructor parameters to the bus, which would register them in its constructor.
If you want to have fairly flexible injection of all the components of a given type (here, you would want to inject all event listeners into the bus), you could use multibindings. However, i don't think we actually use this in our codebase; we just write out manual lists of everything that needs injecting, which turns out not to be all that arduous in practice.
I generally use multiple modules, separated out by logical function. So one module might have authentication in it, another has data repositories, another the messaging system that I'm using, etc. This allows you to have different modules for mocking, caching Vs. non-caching, or just different implementations of the same service, and to switch out chunks of dependencies quickly and easily.
To make things even more flexible you could have a configuration file which declares the modules that should be used when the injector starts up.
When I have some logic to be done right after I instantiate my object I usually do it in methods annotated with #Provides. Your example might looks like this :
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(FizzEventHandler.class).to(DefaultFizzEventHandler.class);
bind(BuzzEventHandler.class).to(DefaultBuzzEventHandler.class);
}
#Provides
public EventBus getEventBus(SimpleEventBuss simpleBus/* this here is going to be injected as it is a class not an interface and Guice is clever and it know how to do it ;) */
, FizzEventHandler fizz, BuzzEventHandler buzz) {
simpleBus.register(fizz);
simpleBus.register(buzz);
return simpleBus;
}
}
I have a use case where it appears that referencing a Guice injector from multiple locations is the only solution—though this is generally discouraged.
My application is built on top of Talend, an open source ETL platform. Most of my actual application is in Java classes that are called by Talend components. These components include Java snippets that I write and that, in turn, instantiate/invoke my classes.
Now I intend to use Guice throughout my Java classes but there is absolutely no way for me to inject dependencies into the Talend components (so that they would be available to the Java snippets). Instead, I need to actually create these dependencies. I’d like to at least have Guice control the instantiation, which means that instead of using new, it appears that the only way I can instantiate my classes (the ones with #Inject constructors) is to call injector.getInstance. This, in turn, implies that I need to keep the injector around, presumably using an old-fashioned factory that creates it in the first place and makes it available as a singleton.
I just can’t see any other way to handle this but perhaps I’m missing something.
Consider static injection. This will still hide persistent references to your injector across your app, but it will save you from having to pepper your code with injector.getInstance(...) calls. In any case you can inject Injector if you really need to.
class TalendDependencyModule extends AbstractModule {
#Override public void configure() {
requestStaticInjection(ExtractorDependencies.class);
requestStaticInjection(ProcessorDependencies.class);
}
}
public class ExtractorDependencies {
#Inject private static Provider<ParserService> parserServiceProvider;
#Inject private static Provider<SomethingElse> somethingElseProvider;
private ExtractorDependencies() { }
static ParserService getParserService() {
return parserServiceProvider.get();
}
/* ... */
}
I don't know how many Talend objects you have but you might want to consider using providers. For instance suppose you have your own class that you want Guice to manage creation of:
public interface INotTalendControlled {}
public class NotTalendControlled implements INotTalendControlled {}
This will be added to a Talend object whose dependencies cannot be injected via Guice (although I assume there is some manual process for doing so either constructor or setter):
public class TalendControlled {
private INotTalendControlled notTalendControlled;
private TalendControlled(INotTalendControlled notTalendControlled) {
this.notTalendControlled = notTalendControlled;
}
public INotTalendControlled getValue() {
return notTalendControlled;
}
}
If you want Guice to manage these lifecycles and the lifecycle of Talend controlled objects you can use a provider like so:
public static class TestModule extends AbstractModule {
#Override
protected void configure() {
bind(INotTalendControlled.class).to(NotTalendControlled.class);
}
#Provides
public TalendControlled provideInjectsToTalendObject(INotTalendControlled notTalendControlled) {
return new TalendControlled(notTalendControlled);
}
}
The #Provides method will hide of the use of new for all objects as you can now directly inject TalendControlled objects (#Inject TalenControlled talendControlled) and an explicit injector is not needed to construct their dependencies.
Firstly i like what Guice does however i have also like to make as few classes in my system public. All services in my system are package private w/ only the interface public. This presents a few problems for Guice if one does not use a provider. I would prefer some alternative that allows me to provide a strategy to do the following:
for component C
requires dependencies X, Y, Z
call this method w/ X, Y, Z to create instance.
.. repeat again for all components.
In step 2 of the above psuedo code Guice now scans for #inject annotations. If this strategy was available I could decide how id like to find my component's dependencies in a generic way.
Unfortunately Module.bind just doesnt work because it works w/ classes literals.
The strategy interface for the above might look like this
interface ComponentDiscoverer {
Set<ComponentDefinition> components();
}
interface ComponentDefinition<T> {
List<RequiredDependency> requiredDependencies(); // similar to Guice's Key
<T> create( List<SatisfiedDependency> dependencies ); // factory method.
}
Guice gets all components by calling a registered ComponentDiscoverer.
It then calls the registered ComponentDiscoverer.components();
For each ComponentDefinition.requiredDependencies()
on demand call ComponentDefinition.create
Is this any built into Guice way or third party library to achieve the above ?
SAMPLE
package companyX;
public interface Service {
void execute();
}
package companyX;
package private class ServiceImpl implements Service {
static ServiceImpl create( Dependency dependency){
return new ServiceImpl( dependency );
}
private ServiceImpl( Dependency dependency ){
}
void execute();
}
package companyX;
package private class ServiceImpl2 implements Service2{
}
package companyX;
public class Factory {
Service alpha( Dependency ){
return ServiceImpl.create( dependency );
}
Service beta( DifferentDependency ){
// boring left out
}
Service2 gamma( AnotherDifferentDependency);
}
My module lives in a different package and all creation goes thru Fatory because everything else is package private.
You shouldn't have just one Module unless your application is very simple. You should have a module for each package that you have package-private classes you want to use in. This allows you to bind those package-private classes to the public interfaces. This is a standard practice for using Guice, and it's mentioned in the Keep Constructors Hidden section of the documentation.
With a module in the package, you just need normal #Injectable constructors or provider methods:
#Provides #Alpha Service alpha(Dependency dependency) {
return ServiceImpl.create(dependency);
}