DEV Community

Sudhakar V
Sudhakar V

Posted on

Inversion of Control (IoC)

Inversion of Control (IoC) is a fundamental principle of the Spring Framework that shifts responsibility for object creation and dependency management from application code to the Spring container. Instead of your code instantiating and wiring its own dependencies, Spring’s IoC container does it for you, leading to looser coupling and more testable, maintainable code.


1. Core Concepts

Term Description
IoC “Inverting” the flow of control—your code delegates control of object creation to a container rather than calling new itself.
DI (Dependency Injection) A common technique for implementing IoC: the container “injects” required dependencies into your objects.
Bean Any object that Spring manages in its container.
BeanFactory The basic, low-level IoC container interface that provides bean instantiation and lifecycle.
ApplicationContext A richer IoC container (supersets BeanFactory) that adds support for internationalization, event propagation, AOP integration, and more.

2. Types of Dependency Injection

  1. Constructor Injection
  • Dependencies are provided as constructor arguments.
  • Enables immutable objects and makes required dependencies explicit.
   @Component
   public class UserService {
     private final UserRepository repo;
     @Autowired
     public UserService(UserRepository repo) {
       this.repo = repo;
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Setter Injection
  • Dependencies are set via JavaBean setter methods.
  • Allows optional dependencies and re-injection.
   @Component
   public class EmailService {
     private MailClient client;
     @Autowired
     public void setMailClient(MailClient client) {
       this.client = client;
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Field Injection (not generally recommended)
  • Dependencies are injected directly into fields.
   @Component
   public class OrderService {
     @Autowired
     private PaymentProcessor processor;
   }
Enter fullscreen mode Exit fullscreen mode

3. How Spring’s IoC Container Works

  1. Configuration
  • Java-based (@Configuration + @Bean methods)
  • Annotation-based (@Component, @Service, @Repository, etc., combined with @ComponentScan)
  • XML (legacy)
  1. Component Scanning & Bean Definitions
  • Spring scans specified packages for annotated classes, registers them as bean definitions.
  1. Dependency Resolution
  • When the container starts, it reads bean definitions, resolves dependencies by type (and qualifier, if needed), and injects them.
  1. Bean Lifecycle
  • InstantiationPopulate properties/injections@PostConstruct / init-methoduse@PreDestroy / destroy-method

4. Bean Scopes

Scope Description
singleton (Default) One shared instance per Spring container.
prototype A new instance each time it’s requested from the container.
request One instance per HTTP request (web applications).
session One instance per HTTP session (web applications).
application One instance per ServletContext (web applications).
@Component
@Scope("prototype")
public class ShoppingCart {  }
Enter fullscreen mode Exit fullscreen mode

5. Putting It All Together: Minimal Example

@Configuration
@ComponentScan("com.example.app")
public class AppConfig { }

@Service
public class GreetingService {
  public String greet() { return "Hello, IoC!"; }
}

@Component
public class Runner {
  private final GreetingService svc;
  @Autowired
  public Runner(GreetingService svc) { this.svc = svc; }
  public void run() { System.out.println(svc.greet()); }
}

public class Main {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx =
      new AnnotationConfigApplicationContext(AppConfig.class);
    Runner runner = ctx.getBean(Runner.class);
    runner.run();  // prints “Hello, IoC!”
    ctx.close();
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. AnnotationConfigApplicationContext creates the IoC container.
  2. It scans for @Service and @Component, builds beans.
  3. It injects GreetingService into Runner’s constructor.
  4. Your application code simply retrieves and uses beans—no new calls!

✨ Benefits of IoC in Spring

  • Loose Coupling: Beans depend on interfaces, not concrete implementations.
  • Testability: Swap real implementations with mocks easily.
  • Configurability: Change wiring via configuration, not code.
  • Maintainability: Centralized control of object lifecycles and dependencies.

Let me know if you’d like a deeper dive—e.g., custom injection annotations, conditional beans, or advanced lifecycle hooks!

Top comments (0)