Dependency bindings are type-checked by the compiler and if any dependency is missing or incompatible, an error message is emitted.
Dependencies are named, so that the compiler can always discern a dependency named "foo" from a "bar", even if they have the same type.
Dependencies are created and (if desired) cached just-in-time by calling abstract methods, so that your application can startup quickly.
No runtime artifacts
All necessary code is generated by the compiler, so that there are no runtime artifacts, and it doesn't break byte code analysis or transformation tools.
Simple and scalable
Dependencies are defined in module contexts or types. Module types can get composed into large systems by composition or inheritance.
Supports Java and Scala
Bali DI is implemented as an annotation processor in Java and as a def macro in Scala. You can even use it in mixed Java/Scala/Scala.js projects.
Mix & match with JSR 330
Bali DI is completely complementary to Spring, Guice, Macwire, CDI or any other JSR 330 implementation, so that you can use both in the same project.
No IDE plugin required
The Java annotation processor emits formatted source code, so that you can easily inspect your dependency bindings and their caching.
Effectively eliminates `new`
The design is based on abstract types, which are hard to implement manually. This is an effective deterrent to accidentally `new` a dependency type.