Discord Build JDK EA License Maven Central javadoc
APT-based dependency injection for server-side developers - https://avaje.io/inject
<dependency> <groupId>io.avaje</groupId> <artifactId>avaje-inject</artifactId> <version>${avaje.inject.version}</version> </dependency>
<dependency> <groupId>io.avaje</groupId> <artifactId>avaje-inject-generator</artifactId> <version>${avaje.inject.version}</version> <scope>provided</scope> </dependency>
@Singleton public class Example { private DependencyClass d1; private DependencyClass2 d2; // Dependencies must be annotated with singleton, // or else be provided from another class annotated with @Factory public Example(DependencyClass d1, DependencyClass2 d2) { this.d1 = d1; this.d2 = d2; } }
Example factory class:
@Factory public class ExampleFactory { @Bean public DependencyClass2 bean() { return new DependencyClass2(); } }
BeanScope beanScope = BeanScope.builder().build() Example ex = beanScope.get(Example.class);
When working with Java modules you need to add a provides statement in your module-info.java with the generated class.
import io.avaje.inject.spi.InjectExtension; module org.example { requires io.avaje.inject; // you must define the fully qualified class name of the generated classes. if you use an import statement, compilation will fail provides InjectExtension with org.example.ExampleModule; }
The inject annotation processor determines the dependency wiring order and generates an AvajeModule class that calls all the generated DI classes.
@Generated("io.avaje.inject.generator") @InjectModule public final class ExampleModule implements AvajeModule { private Builder builder; @Override public Class<?>[] classes() { return new Class<?>[] { org.example.DependencyClass.class, org.example.DependencyClass2.class, org.example.Example.class, org.example.ExampleFactory.class, }; } /** * Creates all the beans in order based on constructor dependencies. The beans are registered * into the builder along with callbacks for field/method injection, and lifecycle * support. */ @Override public void build(Builder builder) { this.builder = builder; // create beans in order based on constructor dependencies // i.e. "provides" followed by "dependsOn" build_example_ExampleFactory(); build_example_DependencyClass(); build_example_DependencyClass2(); build_example_Example(); } @DependencyMeta(type = "org.example.ExampleFactory") private void build_example_ExampleFactory() { ExampleFactory$DI.build(builder); } @DependencyMeta(type = "org.example.DependencyClass") private void build_example_DependencyClass() { DependencyClass$DI.build(builder); } @DependencyMeta( type = "org.example.DependencyClass2", method = "org.example.ExampleFactory$DI.build_bean", // factory method dependsOn = {"org.example.ExampleFactory"}) //factory beans naturally depend on the factory private void build_example_DependencyClass2() { ExampleFactory$DI.build_bean(builder); } @DependencyMeta( type = "org.example.Example", dependsOn = {"org.example.DependencyClass", "org.example.DependencyClass2"}) private void build_example_Example() { Example$DI.build(builder); } }
Similar to Dagger
- Uses Java annotation processing for dependency injection
- Generates source code
- Avoids any use of reflection or classpath scanning (so low overhead and fast startup)
- Specifically aimed for server-side development (rather than Android)
- Supports "component testing" via
avaje-inject-testand@InjectTest - Provides an API to obtain all bean instances that implement an interface
- Lifecycle methods with
@PostConstructand@PreDestroy - Spring-like factory classes with
@Factoryand@Bean - Conditional Wiring based on active profiles or existing beans/properties
| Avaje | Dagger | Spring |
|---|---|---|
| @Singleton | @Singleton | @Component, @Service, @Repository |
| Provider<T> | Provider<T> | FactoryBean<T> |
| @Inject | @Inject | @Inject, @Autowired |
| @Inject @Nullable or @Inject Optional<T> | @Inject @Nullable | @Autowired(required=false) |
| @Qualifier/@Named | @Qualifier/@Named | @Qualifier |
| @AssistFactory | @AssistedFactory | - |
| @PostConstruct | - | @PostConstruct |
| @PreDestroy | - | @PreDestroy |
| @Factory and @Bean | - | @Configuration and @Bean |
| @RequiresBean and @RequiresProperty | - | @Conditional |
| @Lazy | - | @Lazy |
| @Prototype | - | @Scope("prototype") |
| @Primary | - | @Primary |
| @Secondary | - | @Fallback |
| @InjectTest | - | @SpringBootTest |