What's the best way to use Dagger to inject dependencies into classes, especially zero-arg constructor classes like Activities, with Dagger? Will Dagger 2 possibly bring improvements to the situation?
Thanks in advance.
Since Kotlin M13 release, a new property has been especially added in order to support dependency injection (like with Dagger 1&2) and other frameworks.
It's called lateinit property. Taken from the documentation:
class Example {
#Inject
lateinit var bar: Bar
}
In a nutshell, bar has no initializers but is declared as a non-null type. If you try to read it before the initialization, an exception is thrown.
Otherwise, once it's initialized using Dagger, it can be used as a normal property.
Everything is well explained in the language doc and you can also check the blog post relative to the M13 release there.
I wasn't updating my answer for a while and it got outdated. Also noticed here new answer from #Ben that works for M13/M14.
Decided it would best if I redirect all of you interested to my template project which I try to keep up to date with latest Kotlin and Dagger 2 versios. Kotlin + Dagger 2 sample
I am describing there how to inject objects, including multiple annotations etc.
Dagger relies on annotation processing, which is not supported yet in Kotlin, as far as I know. But they say, it is planned. And while, you can either extend java classes with Dagger dependencies, or try some reflection based injection framework - Guice, Roboguice
for using dagger annotations in Kotlin
1- // dagger add dependencies in app level
implementation 'com.google.dagger:dagger:2.38.1'
kapt 'com.google.dagger:dagger-compiler:2.38.1'
add in app level/gradle
plugins {
id 'kotlin-kapt'
}
now you can use annotations like #Inject #Component etc
class Test{
#Inject
lateinit var name: String
}
Related
My question is really a repeat of an old question posted here:
Ninject 2.2 multiple bindings
It seems someone was going to deal with this back in 2011. Does anyone know if there is some way to turn off such warnings in Ninject? Or some other workaround?
EDIT
In response to #BatteryBackupUnit, here is my exact problem:
I have multiple libraries... and in my core library, I do something like this:
Find all assemblies referenced by the host application (including the host)
Find all types inheriting from IDependency from all those assemblies.
Automatically register all of those as transient
Then from another library (which may or may not be referenced by the host app), I have this:
Kernel.Bind<IDbContextFactory>().To<DbContextFactory>().InSingletonScope();
Here IDbContextFactory is also an IDependency, so it got loaded already by the core library and now I register it here but with a different scope (singleton).
From experience (and having tested it earlier) I know this is no problem in Autofac, but Ninject gives me that error message about having already registered it.
Ideally it would be better to just override any previous registrations... "cascade style" (for lack of a better phrase)..
Ninject does now support overriding open generic bindings with more specific ones.
For Example:
public interface IFoo<T> { }
public class Foo<T> : IFoo<T> { }
public class StringFoo : IFoo<string> {}
used like:
var kernel = new StandardKernel();
kernel.Bind(typeof(IFoo<>)).To(typeof(Foo<>));
kernel.Bind<IFoo<string>>().To<StringFoo>();
var intFooInstance = kernel.Get<IFoo<int>>();
var stringFooinstance = kernel.Get<IFoo<string>>();
Works.
However, if you're not talking about open generic bindings, ninject 3 still handles multi bindings the same as ninject 2.2.
In most scenarios you can work around this by using contextual bindings. Okay i would not exactly call it a workaround, i would call it good design.
In general this is described here: https://github.com/ninject/ninject/wiki/Contextual-Binding
A simple way would be to specify the binding using a name. This requires one binding for the specified one and allows only one, too.
See: https://github.com/ninject/ninject/wiki/Contextual-Binding#simple-constrained-resolution-named-bindings
It is also possible to define a "default" binding like .Bind<IFoo>().To<Foo>(); and special case bindings with the .When(...) syntax, like:
.Bind<IFoo>().To<SpecialFoo>().When(ctx => ...)
See https://github.com/ninject/ninject/wiki/Contextual-Binding#specifying-constraints-on-the-type-binding-using-arbitrary-elements-of-the-resolution-request-context
If you show us your concrete problem we might be able to provide a more concrete solution.
Assuming I have a data access object that I've already written, I'd like to be able to use CDI to inject that into say, a service class. Furthermore, I have two implementations of that DAO.
My understanding of CDI is that I'd have to annotate my DAO implementation class so that CDI would know which implementation to inject.
The problem is, the DAO is in a .jar file. By annotating it with CDI annotations, I'm using JavaEE imports in a non-JavaEE class.
For example, let's say I have the following class
public class BusinessService {
#Inject #SomeMybatisQualifier AccountDAO accountDao;
...
}
The #Inject annotation comes from javax.inject.Inject. Now, this service class is dependent on a JavaEE environment.
Can someone please explain to me what I'm missing? How do I inject a non-annotated class into another non-annotated class? This is fairly simple with Spring.
I agree with LightGuard if there's enough classes. But for a couple, why not just produce them with #Produces?
Here's a decent example of implementing your own producer:
Depedency inject request parameter with CDI and JSF2
You should be able to write return new MyObject(); and you can add whatever qualifiers you want
Not sure what's unclear but here's the gist of things: For CDI to scan a jar for beans it must have a beans.xml. Else it will not be scanned and thus not available for injects.A String is not available either. If you try to inject a String say;
#Inject
String myString;
CDI will have no clue what to give you just like your jar. But I know what String I want (a requestparam) and I can let CDI know as well. How? Well I supply a qualifier #RequestParam to my producer (see example again) and now when I want to use it in client code I do it like this:
#Inject
#RequestParam
String myString;
You can do the same thing. Have a producer and just create a new instance of whatever you need and then return it. Now CDI will know just how to dependency inject that particular bean.
Now say you have 40 classes. Then it gets messy to produce them and you want to make sure it gets scanned instead. Then you write your own little extension, observe when CDI is about to scan and instruct it to scan additional jars. Such extension is probably easy to write but I don't know the details because I have not written any extensions like it
By far, the easiest thing would be to create a CDI extension to add the classes in the jar (because there's no beans.xml in that jar so it won't be picked up by CDI) and add additional qualifiers to the metadata.
I have a question regarding dependency injection pattern.
My question is...
If I go for constructor injection, injecting the dependencies for my class, what I get is a "big" constructor with many params.
What if ie. I dont use some of the params in some methods?
Ie. I have a service that exposes many methods. And a constructor with 10 parameters (all dependencies). But not all the methods uses all the dependencies. Some method will use only one dependency, another will use 3 dependencies. But DI container will resolve them all even if non are used.
To me this is a performance penalty of using DI container. Is this true?
It seems your class is doing to much, that it does not comply to the S in SOLID (Single responsibility principle) , maybe you could split the class in multiple smaller classes with less dependencies. The fact that not all dependencies are used by all methods suggests this.
Normally the performance penalty of injecting many dependencies is low, but it depends on the framework you pick. Some will compile methods for this on the fly. You will have to test this. Many dependencies does indicate that your class is doing too much (like Ruben said), so you might want to take a look at that. If creation of an instance of a depedency that you often don't use causes performance problems, you might want to introduce a factory as dependency. I found that the use of factories can solve many problems regarding the use of dependency injection frameworks.
// Constructor
public Consumer(IContextFactory contextFactory)
{
this.contextFactory = contextFactory;
}
public void DoSomething()
{
var context = this.contextFactory.CreateNew();
try
{
// use context here
context.Commit();
}
finally
{
context.Dispose();
}
}
You can also hide some not-yet-needed dependencies behind lazy providers. For instance:
public DataSourceProvider implements Provider<DataSource> {
public DataSource get() {
return lazyGetDataSource();
}
}
The Provider interface is part of javax.inject package.
Actually you can't know which methods are used at runtime when you build your DI container. You would have to deal with that performance penalty or if you know that there are many cases where just a few dependencies are used, you could split your container into several small containers that have less dependencies that are injected.
As rube Says probabily you should review te design of your class to stick to SOLID principles.
Anyway if it is not really necessary I'm used to go for property setter dependency insteadof the constructor. It means that you can create a property for each dependecy you need. That helps also to test the class because you can inject only the dependency you need into the context of the test you are doing instead of stub out all the dependency even if you don't need it
Are there any existing modern-day programming languages that explicitly have dependency injection as a language feature, and if so, are there any examples of how such programming languages use their syntax to separate program dependencies from their concrete implementations?
(Please Note: I'm not looking for an DI/IOC framework--I'm actually looking for a programming language that actually has this feature built into the language).
You won't find dependency injection as a language feature, as it's generally seen as a design pattern. Design patterns arise as workarounds for missing language features - for example if you have first class types as a language feature you don't need the factory pattern ( see p12 of Norvig's presentation ), if you have multi-methods as a language feature you don't need the double dispatch pattern.
The language feature for which DI is the design pattern is "parametric modules". See the discussion of modules vs DI relating to Gilad Bracha's language Newspeak
I don't mean to sound like a jerk, but every OO language supports dependency injection. No special syntax is required. Just construct your object with their dependencies (or set their dependencies later).
You can actually wire up all your dependencies somewhere near the top of the program - not necessarily main(), but close to the top.
Noop supposedly does this, but I haven't seen the language specification (my patience ran out before I found it).
One could say that Scala supports dependency injection out of the box with the help of traits and self-type annotations. Take a look on a Cake Pattern:
http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/
Basically, this approach uses traits with declared dependencies (by using self-types) to let the compiler do the work of wiring them together.
This is the declaration registry:
object ComponentRegistry extends
UserServiceComponent with
UserRepositoryComponent
{
val userRepository = new UserRepository
val userService = new UserService
}
...registering the user repository:
trait UserRepositoryComponent {
val userRepository: UserRepository
class UserRepository {
...
}
}
...and the user service component that depends on the repository:
trait UserServiceComponent {
this: UserRepositoryComponent =>
val userService: UserService
class UserService {
...
}
}
What is your advice?
I found most suitable for me solution - keep injectors and modules in enumeration classes.
Advantages:
injectors and modules created once,
injectors can be used from different classes while running application (not only at bootstrap),
injectors kept in one place and can be easily found.
Example:
import static ru.package.Modules.*;
public enum Injectors {
FOO_INJECTOR(BarModule.module()),
FOO2_INJECTOR(FOO_INJECTOR.injector(),
Bar2Module.module(), FooModule.module());
private final Injector m_injector;
Injectors (Module... modules) {
m_injector = Guice.createInjector(modules);
}
Injectors (Injector parentInjector, Module... modules) {
m_injector = parentInjector.createChildInjector(modules);
}
public Injector injector() {
return m_injector;
}
}
You appear to be fundamentally misunderstanding how dependency injection works. If you are trying to use a reference to Injector anywhere in your code besides the place where you bootstrap the application, you're not using dependency injection, you're using it as a Service Locator instead. You're forced to prepare an Injector whenever you need to test a class and your classes do not make it clear in their constructors exactly what their dependencies are (since who knows what they'll get out of the Injector in some method if they have or can get a reference to it). Actually, using enum as you've described here is even worse than that: you cannot change the configuration at all, even for testing, because your modules are hardcoded into the enum.
With dependency injection, classes declare their dependencies only and allow the Injector, working transparently (after the initial call to get the root application object), to provide all those dependencies. This makes understanding, testing and changing functionality in your code relatively easy. Anyway, I'd suggest learning more about how DI and Guice are intended to be used... you really should not want to do this.
The bigger question is why?
There should be no need to keep the Injector around, because once the injection is done the Injector should be done and should disappear.
If, however, you really need the Injector, couldn't you simply:
#Inject
private Injector injector;
Is this application web based or is it standalone?