Spring Framework Explained (With Real-World Example)

📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.

✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.

🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.

▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube

 🧾 Introduction: What Is Spring Framework?

The Spring Framework is a powerful, open-source platform for building Java-based enterprise applications. It provides a comprehensive infrastructure for managing dependencies, enabling modular development, and simplifying backend architecture — all while keeping your code clean, testable, and loosely coupled.

At the heart of Spring lies one key idea: Inversion of Control (IoC) — which means that instead of your application creating objects, the framework does it for you. This is what the Spring container does — and this is where terms like BeanFactory and ApplicationContext come in.

In this article, you’ll learn:

  • What the Spring container is
  • What are beans and how they’re managed
  • The difference between BeanFactory and ApplicationContext
  • When to use each one
  • And finally — a complete real-world project example to tie it all together

Let’s get started.

What Is the Spring Container?

Imagine you’re building a food delivery app. You have services like:

  • OrderService
  • UserService
  • NotificationService

These services need to work together. In a typical Java app, you might manually create objects and pass them around. But in Spring, you declare what you need, and the framework injects those dependencies for you.

This behavior is powered by the Spring container — the core engine that creates, wires, and manages all the beans (objects) in your app.

There are two types of Spring containers:

  1. BeanFactory
  2. ApplicationContext

Let’s understand each of these with examples.

🧾 What Is a Bean in Spring?

In Spring, a bean is simply a Java object that’s managed by the container. Any service, component, or class can be a bean if it’s annotated or declared in configuration.

For example:

@Component
public class EmailService {
public void sendWelcomeEmail(String email) {
System.out.println("Sending welcome email to " + email);
}
}

The Spring container creates this EmailService bean, manages its lifecycle, and injects it wherever needed.


🧰 Real-World Scenario: User Registration Flow

Let’s say you’re building a user registration feature. Here are your components:

  1. UserService — Handles registration logic
  2. EmailService — Sends welcome emails
  3. DatabaseConfig — Manages database connection
  4. AppConfig — Spring configuration class

In a Spring application, you don’t manually instantiate these classes. Instead, you let Spring do it by declaring beans or using annotations like @Component, @Service, and @Configuration.

Let’s implement this using both BeanFactory and ApplicationContext.


🔍 BeanFactory: The Minimal Container

BeanFactory is the basic Spring container. It’s simple and lazy — meaning it creates objects only when you ask for them.

Step 1: Define Beans in XML

<!-- beans.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
>


<bean id="emailService" class="com.example.EmailService" />
<bean id="userService" class="com.example.UserService">
<property name="emailService" ref="emailService"/>
</bean>
</beans>

Step 2: Load with BeanFactory

Resource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);

UserService userService = factory.getBean("userService", UserService.class);
userService.register("ravi@example.com");

Output:

User registered: ravi@example.com
Sending welcome email to ravi@example.com

But there’s a problem — BeanFactory doesn’t support annotations, event publishing, or AOP by default. That’s why we move to…


⚡ ApplicationContext: The Real Powerhouse

ApplicationContext is the full-featured container. It eagerly loads beans, supports internationalization, application events, and auto-wiring — and is used by default in Spring Boot.

Let’s build the same feature using Java-based configuration and ApplicationContext.


Step 1: Create Your Beans

@Service
public class EmailService {
public void sendWelcomeEmail(String email) {
System.out.println("Sending welcome email to " + email);
}
}
@Service
public class UserService {

private final EmailService emailService;

// Constructor injection
public UserService(EmailService emailService) {
this.emailService = emailService;
}

public void register(String email) {
System.out.println("User registered: " + email);
emailService.sendWelcomeEmail(email);
}
}

Step 2: Configuration Class

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

Step 3: Load with ApplicationContext

public class App {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

UserService userService = context.getBean(UserService.class);
userService.register("anita@example.com");
}
}

Output:

User registered: anita@example.com
Sending welcome email to anita@example.com

✅ Key Differences: BeanFactory vs ApplicationContext

📚 When to Use Which?

  • Use ApplicationContext for all production applications.
  • Use BeanFactory only in lightweight test cases or low-resource environments (very rare today).

If you’re working with Spring Boot, you’re already using ApplicationContext under the hood.


🧵 Digging Deeper: Types of ApplicationContext

Spring provides different implementations for different needs:

👨‍🔧 Tips for Clean Spring Architecture

  • Use constructor injection (better for immutability and testing)
  • Keep beans focused — follow Single Responsibility Principle
  • Use @ComponentScan to automatically discover beans
  • Prefer Java config (@Configuration) over XML

🎓 Final Thoughts

The Spring container is the backbone of any Spring application. Whether you’re building a simple command-line app or a complex microservice, understanding how beans are created and managed helps you write cleaner, testable, and maintainable code.

To recap:

  • BeanFactory is basic — good to know, but rarely used.
  • ApplicationContext is what you’ll use 95% of the time.
  • Spring Boot apps use ApplicationContext automatically — no manual setup needed.
When in doubt, just remember: Let Spring do the wiring, and you focus on writing the logic.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare