Bali DI

Modern compile-time dependency injection with just-in-time resolution for Java, Scala and Scala.js.

Quick Start →

Compile-time bindings

Dependency bindings are type-checked by the compiler and if any dependency is missing or incompatible, an error message is emitted.

Named dependencies

Dependencies are named, so that the compiler can always discern a dependency named "foo" from a "bar", even if they have the same type.

Just-in-time resolution

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.