Interface DependencyContainer

All Superinterfaces:
AutoCloseable, Terminable

public interface DependencyContainer extends Terminable
A dependency injection container that manages singleton instances with auto-injection.

The container supports two modes:

  • Manual registration: Register pre-created instances that you control
  • Auto-creation: Classes annotated with @Component are automatically created with dependencies injected

All instances are singletons - only one instance per type is created and cached. Instances implementing AutoCloseable are automatically cleaned up when the container is closed.

Example usage:


 // Manually create and register core services
 DatabaseConnection db = new DatabaseConnection(plugin);
 CacheService cache = new CacheService();

 DependencyContainer container = DependencyContainer.builder()
     .register(plugin)
     .register(db)
     .register(cache)
     .build();

 // Classes marked with @Component are auto-created with dependencies injected
 @Component
 public class PlayerDataManager {
   private final DatabaseConnection db;
   private final CacheService cache;

   public PlayerDataManager(DatabaseConnection db, CacheService cache) {
     this.db = db;
     this.cache = cache;
   }
 }

 // Auto-creates PlayerDataManager with db and cache injected from registry
 PlayerDataManager manager = container.getInstance(PlayerDataManager.class);
 
  • Method Details

    • builder

      @NotNull static @NotNull DependencyContainer.Builder builder()
      Creates a new builder for configuring a dependency container.
      Returns:
      A new builder instance
    • register

      @NotNull <T> @NotNull DependencyContainer register(@NotNull T instance)
      Registers an instance in the container.

      The instance will be registered under its actual runtime class type and returned whenever that type is requested from the container.

      Type Parameters:
      T - The type parameter
      Parameters:
      instance - The instance to register
      Returns:
      This container for method chaining
    • register

      @NotNull <T> @NotNull DependencyContainer register(@NotNull @NotNull Class<T> type, @NotNull T instance)
      Registers an instance in the container with an explicit type.

      This allows registering instances by their interface or abstract class rather than just their concrete implementation type, enabling programming to interfaces and dependency inversion principle.

      Example usage:

      
       // Register by interface
       PlayerService service = new PlayerServiceImpl();
       container.register(PlayerService.class, service);
      
       // Can now retrieve by interface in @Component classes:
       @Component
       public class GameManager {
         private final PlayerService playerService;
      
         public GameManager(PlayerService playerService) {
           this.playerService = playerService;
         }
       }
       
      Type Parameters:
      T - The type parameter
      Parameters:
      type - The type to register the instance under (interface or class)
      instance - The instance to register
      Returns:
      This container for method chaining
      Throws:
      TypeMismatchException - if instance is not assignable
    • getInstance

      @NotNull <T> T getInstance(@NotNull @NotNull Class<T> type)
      Gets an instance of the specified type from the container.

      If the instance is already registered or created, it returns the cached instance. If the class is annotated with @Component, it will be auto-created with dependencies injected from the container.

      Type Parameters:
      T - The type parameter
      Parameters:
      type - The class type to get an instance of
      Returns:
      The instance (either registered or auto-created)
      Throws:
      MissingDependencyException - if no instance is registered and class is not annotated with @Component
      DependencyException - if a circular dependency is detected or instance creation fails
    • hasInstance

      boolean hasInstance(@NotNull @NotNull Class<?> type)
      Checks if an instance is registered for the given type.
      Parameters:
      type - The class type to check
      Returns:
      True if an instance is registered, false otherwise