Spring BootSpring Corebeginner
Updated:

Inversion of Control (IoC) in Spring

6 min read

IoC is the single idea Spring is built on: your objects stop creating their own dependencies and the container takes over. Here is what that really means, with code.

TL;DR – Quick Answer

Inversion of Control means handing the job of creating and wiring objects over to a framework instead of doing it yourself with new. In Spring, the IoC container reads your configuration, builds your objects (beans), injects their dependencies, and manages their lifecycle. Control over object creation is inverted from your code to the container, which is why your classes become loosely coupled and easy to test.

On This Page

Inversion of Control is the phrase that scares beginners and the concept that unlocks all of Spring. It sounds abstract, but the idea is concrete: stop letting your objects create the things they depend on, and let a container do it instead. That one change is what everything else in the framework rests on.

This page walks through what "inverting control" actually inverts, how Spring's container implements it, and where IoC ends and dependency injection begins — a distinction interviewers love to probe.

What control are we inverting?

In ordinary Java, your code holds control over the whole flow, including which objects get created and when. A report generator that needs a data source builds it itself:

public class ReportGenerator {
    private final DataSource dataSource;

    public ReportGenerator() {
        // MY code decides which DataSource and how to configure it
        this.dataSource = new MySqlDataSource("localhost", 3306, "sales");
    }

    public Report build() {
        // use dataSource to fetch rows and assemble a report
        return new Report(dataSource.fetchRows());
    }
}

Here ReportGenerator is in charge. It knows the exact class, the host, the port, the database name. That control feels natural, but it is also what makes the class rigid: it can only ever use a MySqlDataSource, configured exactly this way.

Inversion of Control asks: what if ReportGenerator gave up that control? What if it simply said "I need a DataSource" and left the choosing and building to someone else? That someone else is the container, and handing over the decision is the "inversion".

The inverted version

With IoC, the class declares its need and receives the object from outside:

import org.springframework.stereotype.Component;

@Component
public class ReportGenerator {
    private final DataSource dataSource;

    // I no longer build my dependency. The container passes it in.
    public ReportGenerator(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Report build() {
        return new Report(dataSource.fetchRows());
    }
}

The class no longer names a concrete MySqlDataSource, no longer knows the host or port. The container decides which DataSource bean to supply, based on configuration, and injects it. Control over creation moved from the class to the container — that is inversion of control in one diff.

Pro tip: The cleanest interview line is: "Normally my code controls object creation. With IoC, I give that control to the container — I declare what I need, it decides how to build and supply it." Follow it with the two-line before/after above and you have answered the question and its usual follow-up in one breath.

IoC vs dependency injection

This trips up a lot of candidates, so pin it down. Inversion of Control is the broad principle: something other than your own code controls the flow and object creation. Dependency Injection is one technique that achieves IoC — specifically, supplying a class's dependencies from outside through its constructor, a setter, or a field.

Put simply: DI is how Spring implements IoC. There are other ways to invert control (like the service locator pattern or template methods), but Spring standardises on injection. When an interviewer asks you to distinguish the two, say "IoC is the goal, DI is the mechanism" and give an example. The mechanics of the three injection styles are covered in dependency injection in Spring.

The IoC container: ApplicationContext

The concrete thing that performs inversion of control in Spring is the IoC container. It reads your configuration (annotations, Java config, or legacy XML), builds every bean, resolves the dependency graph, injects everything, and manages lifecycles. You usually meet it through the ApplicationContext interface.

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {
    public static void main(String[] args) {
        // Starting the context IS starting the IoC container
        ApplicationContext context =
            new AnnotationConfigApplicationContext(AppConfig.class);

        // The container already built and wired ReportGenerator
        ReportGenerator generator = context.getBean(ReportGenerator.class);
        Report report = generator.build();
        System.out.println(report);
    }
}

By the time getBean returns, the container has already constructed ReportGenerator, found a DataSource bean, and injected it. You never wrote new ReportGenerator(...). That is the container earning its keep.

There are two container types worth knowing. BeanFactory is the minimal one — lazy bean creation and basic injection. ApplicationContext builds on it with eager singleton instantiation, event publishing, message resolution and annotation support. In real applications you use ApplicationContext; Spring Boot creates one for you automatically.

Why the inversion pays off

Giving up control feels like a loss until you see what you gain. Because ReportGenerator depends only on the DataSource interface and receives its instance from outside, three things become easy:

  • Swapping implementations — point the container at a PostgresDataSource bean instead, and no business class changes.
  • Testing in isolation — inject a fake DataSource returning canned rows, and test the report logic with no real database.
  • Central configuration — object graphs and their settings live in one place, not scattered across constructors.

This is the same "depend on abstractions" discipline that good object-oriented design teaches; if the underlying principle feels shaky, the OOP concepts guide reinforces why coupling to interfaces beats coupling to concrete classes.

Common mistake: Thinking IoC means "Spring magically knows everything". It does not — it only knows what you tell it through annotations and configuration. If two beans could satisfy one dependency and you have not qualified which, the container throws an error. IoC automates wiring; it does not read your mind.

Where beans and lifecycle fit

Everything the container manages is a bean. Understanding IoC naturally leads into two neighbouring topics: what beans are and how you define them, covered in Spring beans, and the sequence each bean passes through from creation to destruction, covered in the bean lifecycle. IoC is the principle; beans are the things it produces; the lifecycle is how long they live.

It also explains why Spring Boot feels so effortless. Boot is essentially "IoC with sensible defaults" — it auto-detects your components, builds the container, and wires everything before your first line runs. The container concept you learn here is exactly what Boot automates; see what is Spring Boot for that layer.

The Hollywood Principle

IoC is sometimes summarised as the "Hollywood Principle": don't call us, we'll call you. The phrase captures the shift in who is in charge. In traditional code, your class calls out to fetch and build what it needs. Under IoC, the framework is in charge of the flow, and it calls into your code — creating your objects and invoking your methods at the right time.

You see this everywhere in Spring once you notice it. You do not call Spring to build your controller; Spring builds it and calls its methods when a request arrives. You do not invoke a lifecycle callback; the container invokes yours during startup. Control of the overall flow has moved to the framework, and your code plugs into the points it exposes. That mental model makes the whole framework easier to reason about.

IoC beyond object creation

Injecting dependencies is the most visible form of IoC, but the principle runs wider in Spring. The container also controls when your beans are created (eagerly at startup for singletons, lazily on demand if you ask), how long they live, and when their lifecycle callbacks fire.

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

@Component
public class ConnectionPool {

    @PostConstruct   // the container calls this AFTER wiring, not you
    public void open() {
        System.out.println("Opening connections...");
    }

    @PreDestroy      // the container calls this at shutdown
    public void close() {
        System.out.println("Closing connections...");
    }
}

You never invoke open() or close() yourself — you annotate them and the container calls them at the right moment. That is inversion of control applied to lifecycle, not just creation, and it is the foundation of the full bean lifecycle. The consistent theme across all of it: you declare intent, the container controls execution.

Bringing it together

Inversion of Control is a small idea with a large payoff. Your classes stop creating their own dependencies and instead declare what they need; the IoC container — usually an ApplicationContext — creates the objects, injects the dependencies through injection, and manages their lives. The result is loosely coupled, testable, reconfigurable code.

Get comfortable saying the definition in your own words, drawing the before/after diff, and distinguishing IoC (the principle) from DI (the technique). Then move on through the Spring Boot learning path to dependency injection and beans, and test yourself with the Spring Boot fresher interview questions. Once IoC is intuitive, the rest of Spring reads like variations on a theme you already know.

Frequently Asked Questions

What is inversion of control in simple terms?
Normally your code is in control: it decides when and how to create the objects it needs. With inversion of control, that decision is handed to a framework. Your class just declares what it needs, and the container creates and supplies it, so control over object creation is inverted from you to the container.
What is the difference between IoC and dependency injection?
IoC is the broad principle: something other than your own code controls object creation and flow. Dependency injection is one specific way to achieve IoC, where the container supplies a class's dependencies through its constructor, setter or field. In Spring, DI is the mechanism the IoC container uses.
What is the IoC container in Spring?
It is the part of Spring that implements inversion of control. It creates beans, resolves and injects their dependencies, and manages their lifecycle. You interact with it through the BeanFactory or, more commonly, the richer ApplicationContext interface.
What is the difference between BeanFactory and ApplicationContext?
BeanFactory is the basic container that provides dependency injection and lazy bean creation. ApplicationContext extends it with enterprise features like event publishing, internationalization, annotation support and eager singleton creation. In practice you almost always use ApplicationContext.
Why is inversion of control useful?
It removes object-creation logic from your business classes, so they depend on interfaces rather than concrete implementations. That makes code loosely coupled, easy to test with fakes or mocks, and simple to reconfigure without editing the classes themselves. It is the foundation that makes Spring's other features possible.

Want to Build Your Career in Java Full Stack with AI?

Join CodeBegun and train with working industry engineers — Explore the Program

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 15 July 2026 LinkedIn
Chat with us