What types of dependency injection do you know?
sobes.tech AI
Answer from AI
There are three main types of dependency injection:
-
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.
-
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.
-
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.