Sobes.tech
Junior

What types of dependency injection do you know?

sobes.tech AI

Answer from AI

There are three main types of dependency injection:

  1. Constructor Injection: Dependencies are provided through the class constructor arguments. The class cannot be created without its dependencies.

    // Example of constructor injection
    public class MyService {
        private MyDependency dependency;
    
        public MyService(MyDependency dependency) { // Dependency injected via constructor
            this.dependency = dependency;
        }
    
        public void performAction() {
            dependency.doSomething();
        }
    }
    
    • Pros: Ensures immutability, makes class dependencies explicit, simplifies unit testing (dependencies can be easily replaced).
    • Cons: Can lead to bloated constructors when there are many dependencies.
  2. Setter Injection: Dependencies are provided through public setter methods after the class instance is created.

    // Example of setter injection
    public class AnotherService {
        private AnotherDependency dependency;
    
        public AnotherService() {
        }
    
        public void setDependency(AnotherDependency dependency) { // Dependency injected via setter
            this.dependency = dependency;
        }
    
        public void executeTask() {
            if (dependency != null) {
                dependency.performTask();
            }
        }
    }
    
    • Pros: Optional dependencies can be injected. Allows cyclic dependencies (though this often indicates poor design).
    • Cons: The class may be in an incomplete or non-functional state until all dependencies are injected. Does not guarantee that the dependency is set.
  3. Interface Injection: The class implements an interface that contains one or more methods for dependency injection. The DI container uses this interface to inject dependencies into implementing objects.

    // Example of interface injection
    // Not as common as Constructor or Setter Injection in modern frameworks
    
    // 1. Define an interface for injection capability
    public interface DependencyInjectable {
        void injectDependency(InterfaceDependency dependency);
    }
    
    // 2. Implement the interface in the class needing the dependency
    public class FinalService implements DependencyInjectable {
        private InterfaceDependency dependency;
    
        @Override
        public void injectDependency(InterfaceDependency dependency) { // Dependency potentially injected via interface method
            this.dependency = dependency;
        }
    
        public void processData() {
            if (dependency != null) {
                dependency.process();
            }
        }
    }
    
    // 3. (Conceptual example in a framework)
    // Framework might scan for services implementing DependencyInjectable
    // and call injectDependency on them during initialization.
    
    • Pros: Less intrusive than constructor or setter, as the class explicitly declares its ability to accept dependencies through a contract (interface).
    • Cons: Not widely used in modern DI frameworks compared to constructor and setter injection. Requires additional structure (interface).

Although other options exist, such as field injection, which is used in some frameworks (e.g., Spring, Guice), constructor injection is considered the classic and most recommended approach, especially in the context of testability.

What types of dependency injection do you know? — Java - sobes.tech