Avaje-Inject

April 22, 2026 · View on GitHub

Supported JVM Versions Discord Build License Maven Central javadoc GraalVM Native Image

Avaje-Inject

Annotation-processor-based dependency injection for server-side developers - https://avaje.io/inject

Documentation

Quick Start

1. Add avaje-inject as a dependency.

Maven

<dependency>
  <groupId>io.avaje</groupId>
  <artifactId>avaje-inject</artifactId>
  <version>${avaje.inject.version}</version>
</dependency>

Gradle

implementation 'io.avaje:avaje-inject:${avaje.inject.version}'

2. Add avaje-inject-generator annotation processor as a dependency with provided scope.

Maven

<dependency>
  <groupId>io.avaje</groupId>
  <artifactId>avaje-inject-generator</artifactId>
  <version>${avaje.inject.version}</version>
  <scope>provided</scope>
</dependency>

Gradle

annotationProcessor 'io.avaje:avaje-inject-generator:${avaje.inject.version}'

3. Optionally add avaje-inject-test for integration testing.

Maven

<dependency>
  <groupId>io.avaje</groupId>
  <artifactId>avaje-inject-test</artifactId>
  <version>${avaje.inject.version}</version>
  <scope>test</scope>
</dependency>

Gradle

testImplementation 'io.avaje:avaje-inject-test:${avaje.inject.version}'

4. Create a Bean Class annotated with @Singleton

@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();
  }
}

5. Use BeanScope to wire and retrieve the beans and use them however you wish.

BeanScope beanScope = BeanScope.builder().build()
Example ex = beanScope.get(Example.class);

Generated Wiring Class

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 {

  /**
   * 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(builder);
    build_example_DependencyClass(builder);
    build_example_DependencyClass2(builder);
    build_example_Example(builder);
  }

  @DependencyMeta(type = "org.example.ExampleFactory")
  private void build_example_ExampleFactory(Builder builder) {
    ExampleFactory$DI.build(builder);
  }

  @DependencyMeta(type = "org.example.DependencyClass")
  private void build_example_DependencyClass(Builder builder) {
    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(Builder builder) {
    ExampleFactory$DI.build_bean(builder);
  }

  @DependencyMeta(
      type = "org.example.Example",
      dependsOn = {"org.example.DependencyClass", "org.example.DependencyClass2"})
  private void build_example_Example(Builder builder) {
    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)

Differences to Dagger

  • Specifically aimed for server-side development (rather than Android)
  • Supports "component testing" via avaje-inject-test and @InjectTest
  • Provides an API to obtain all bean instances that implement an interface
  • Lifecycle methods with @PostConstruct and @PreDestroy
  • Spring-like factory classes with @Factory and @Bean
  • Conditional Wiring based on active profiles or existing beans/properties

DI Framework comparison

AvajeDaggerSpring
@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