If you have written plain Java for a while, you know the quiet pain: every class creates the
objects it needs with new, passes them around by hand, and closes them when done. That
plumbing grows faster than the actual features. The Spring Framework exists to take that
plumbing away so you write business logic instead.
This page explains what Spring actually is, the one idea at its centre, and the modules built around it. Once this clicks, everything in Spring Boot stops looking like magic.
The problem Spring solves
Consider a service that sends order confirmations. In plain Java it might look like this:
public class OrderService {
private final EmailSender emailSender;
public OrderService() {
// OrderService decides HOW to build its own dependency
this.emailSender = new SmtpEmailSender("smtp.gmail.com", 587);
}
public void placeOrder(Order order) {
// ... save order ...
emailSender.send(order.getEmail(), "Your order is confirmed");
}
}
Notice the trap: OrderService is now permanently married to SmtpEmailSender and its
constructor arguments. Want to send through a different provider in production? Want a fake
sender in tests so no real email goes out? You cannot, without editing OrderService
itself. Every class knowing how to build its collaborators is what makes large codebases
rigid.
Spring flips this around. Your class simply declares what it needs; something else decides which implementation to supply and builds it. That "something else" is the Spring container, and the flip is called Inversion of Control.
The core idea: the IoC container
The heart of Spring is the IoC container. You register your classes with it (usually just by annotating them), and the container becomes responsible for creating those objects, wiring their dependencies, and managing how long they live. An object the container manages is called a bean.
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private final EmailSender emailSender;
// OrderService no longer builds EmailSender.
// It just asks for one, and Spring supplies it.
public OrderService(EmailSender emailSender) {
this.emailSender = emailSender;
}
public void placeOrder(Order order) {
emailSender.send(order.getEmail(), "Your order is confirmed");
}
}
@Service tells Spring "manage this class as a bean". The constructor parameter tells
Spring "I need an EmailSender — you find and inject the right one". At startup, the
container sees that OrderService needs an EmailSender, finds a bean that fits, and hands
it over. Your class never says new SmtpEmailSender(...) again.
This is worth reading twice because it is the whole point of Spring. The mechanics are covered in depth in Inversion of Control in Spring and dependency injection in Spring, and the managed objects themselves in Spring beans.
Pro tip: When someone asks "what is Spring, in one sentence?", answer with the job, not the definition: "Spring is a container that creates my objects and injects their dependencies, so my classes stay loosely coupled." That single sentence signals you understand the framework rather than having read a feature list.
What loose coupling buys you
The payoff of letting the container wire things is that OrderService now depends on the
EmailSender interface, not any concrete class. You can swap implementations without
touching the service:
public interface EmailSender {
void send(String to, String message);
}
@Service
public class SmtpEmailSender implements EmailSender {
public void send(String to, String message) {
// real SMTP work
}
}
// In a test, provide a fake instead — OrderService never changes
public class FakeEmailSender implements EmailSender {
public void send(String to, String message) {
System.out.println("Pretend-sent: " + message);
}
}
Because OrderService only knows the interface, testing it in isolation becomes trivial and
switching providers becomes a configuration decision, not a code rewrite. This dependence on
interfaces rather than concrete classes is exactly the design principle that Java's
interfaces teach, and Spring is what makes it practical at
scale.
The modules around the core
The container is the foundation, but "the Spring Framework" is really a family of modules that all build on it. You pull in only the ones you need.
| Module | What it gives you |
|---|---|
| Core / Beans | The IoC container, dependency injection |
| Context | ApplicationContext, events, resource loading |
| Spring MVC | Build web apps and REST controllers |
| Spring Data / JDBC | Talk to databases with far less boilerplate |
| Transactions | Declarative @Transactional rollback handling |
| Spring Security | Authentication and authorization |
| Test | First-class support for testing Spring components |
The important mental model: these modules are not separate frameworks glued together. They
all speak the same language of beans and injection, so a @Service you write can be handed
a data-access bean, wrapped in a transaction, and secured — with the container coordinating
all of it.
How it runs at startup
When a Spring application starts, the container performs a predictable sequence: it scans for your annotated classes, works out the dependency graph, then instantiates and injects beans in the right order. By the time your code runs, every object is already wired.
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
// Boot up the container; it builds and wires all beans
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
// Ask the container for a fully-wired OrderService
OrderService service = context.getBean(OrderService.class);
service.placeOrder(new Order("ravi@example.com"));
}
}
You rarely write this bootstrap by hand once you use Spring Boot — it does it for you — but seeing it clarifies what Boot automates. Each bean also passes through a defined bean lifecycle of creation, initialization and destruction that you can hook into.
Common mistake: Beginners assume Spring is "just annotations" and skip the container concept. Then a
NoSuchBeanDefinitionExceptionor a wiring failure appears and there is no mental model to debug it. Learn what the container does first; the annotations are just how you talk to it.
Spring Framework vs Spring Boot
A fair question at this point: if Spring is so good, why does everyone talk about Spring Boot? Because classic Spring, in its early years, required a lot of XML configuration and manual setup — powerful but slow to start. Spring Boot keeps the same framework underneath and adds sensible defaults, auto-configuration and an embedded server so you can run a real application in minutes.
You are always using the Spring Framework when you use Spring Boot; Boot is the convenience layer, not a replacement. The full comparison lives in Spring vs Spring Boot, and the Boot side is introduced in what is Spring Boot.
A short history, and why it still leads
Spring appeared in the early 2000s as a reaction to the heavyweight enterprise Java of the time, which forced developers into rigid, hard-to-test components. Spring's pitch was simple: your business classes should be plain Java objects, and a lightweight container should handle the wiring. That idea aged extremely well. As the framework grew, the modules multiplied, but the container at the centre never changed its job.
The reason it still leads in 2026 is that the core abstraction is genuinely good. Loose coupling through injection makes large systems maintainable, and every new capability — cloud config, reactive programming, native compilation — plugs into the same bean model. You are not betting on a fad; you are learning an abstraction that has survived two decades of change and absorbed each new trend rather than being replaced by it.
How Spring changes the way you design
Working with Spring nudges you toward a particular, healthier style of design. Because the container injects dependencies, you naturally program to interfaces rather than concrete classes — otherwise there is nothing for the container to swap. Because objects do not build their own collaborators, your classes end up smaller and single-purpose. And because wiring is external, testing becomes a first-class concern instead of an afterthought.
// A unit test — no Spring container needed, just plain construction
class OrderServiceTest {
@Test
void sendsConfirmationOnPlaceOrder() {
FakeEmailSender fake = new FakeEmailSender();
OrderService service = new OrderService(fake); // inject the fake by hand
service.placeOrder(new Order("ravi@example.com"));
assertTrue(fake.wasCalled()); // verify behaviour with no real email sent
}
}
Notice you can test OrderService completely without starting Spring, because its dependency
arrives through the constructor. That testability is not a lucky side effect — it is the
direct consequence of letting the container own object creation. Frameworks that hide their
wiring make this hard; Spring makes it the default path.
Why this matters for your career
For anyone targeting a Java backend or full stack role in India, Spring and Spring Boot are close to non-negotiable — most job descriptions that say "Java" also say "Spring Boot". Interviewers almost always open with conceptual questions here, which is why the Spring Boot fresher interview set is worth working through once the concepts land.
The good news: the core idea is small. Object creation moves out of your classes and into a container; your classes just declare their needs. Everything else in Spring — MVC, Data, Security — is a module that trusts that container to do the wiring. Start from the Spring Boot learning hub and build the concepts in order, and the framework stops feeling large and starts feeling like one idea applied consistently.
Frequently Asked Questions
What is the Spring Framework used for?
Is Spring Framework the same as Spring Boot?
Do I need to learn core Spring before Spring Boot?
What is the IoC container in Spring?
Is the Spring Framework still relevant in 2026?
Want to Build Your Career in Java Full Stack with AI?
Join CodeBegun and train with working industry engineers — Explore the Program

