Skip to content

schrer/inject

Repository files navigation

inject - a Java dependency injection library

Implementation of a dependency injection library for Java 21. This is only a pastime, so it is neither complete nor tested. I also did not look up best practices, no guarantees are made, you know the drill.

Basic features and restrictions are:

  • Create contexts with a specified package coverage
    • Specify several packages. Components can depend on components from other packages
    • Reuse of existing component contexts if same package coverage is requested again
    • Fail early when context is inconsistent or contains cyclic dependencies
  • Component registration via annotation
    • Register classes as "Components" for injection via annotation
    • Mark methods with a return type as Component sources to create instances from their classes
    • Specify a name for components to support multiple alternative implementations of an interface or abstract class, as well as basic types like String and Integer
    • Singleton scope for all components within one context
  • Injection of other components
    • Mark constructor/component source function parameters with the @ByName annotation for matching by component name
    • No field injection
    • Interfaces and abstract classes supported for injection or explicit instance loading

Usage

Mark your classes and functions with the annotation @Component, then use the class ContextBuilder to load your Java package and build instances of your classes.

A minimal example application to showcase the usage can be found in my other repository

Define a class as component

The constructor is then used to instantiate it, any constructor parameters will be injected.

@Component
public class YourService {
    private final Repository repository;
    
    public YourService(Repository repository){
        this.repository = repository;
    }
    // Business logic
}

BeanSource and parameter injection by name

The @BeanSource annotation can be used to mark classes as containing static methods that produce components. The @ByName annotation identifies beans by name in addition to their class when injecting.

@BeanSource
public class BeanSource {
    @Component(name = "namedString")
    public static String namedString() {
        return "Some string that will be a component";
    }

    public static YourOtherService someClassInstance(
            @ByName("namedString") String parameter
    ) {
        return new YourOtherService(parameter);
    }
}

Using the ContextBuilder to get instances

// Create context once
ContextBuilder contextBuilder = ContextBuilder.getContextInstance("at.schrer.inject", "at.schrer.example", "at.schrer.util");

// Request instances
YourService service1 = contextBuilder.getComponent(YourService.class);

// YourOtherService will be identified by its name, so you can have several instances with different names in your context
YourOtherService service2 = contextBuilder.getComponent("serviceName", YourOtherService.class);

Notable classes

  • The ContextBuilder, which can instantiate classes marked with the annotation @Component from a provided package.
  • The ClassScanner, which is able to return a list of classes under a provided package name. The classes can also be filtered by annotations.
  • An implementation of an acyclic graph. It is used in the ContextBuilder to build the dependency graph between all components.

About

A dependency injection library for Java

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages