# Spring framework part 2.

## Topics:  
POJO  
Tightly coupled  
Loosely coupled  
Dependency Injection and IOC(Inversion of control )  
Bean  
Application Context  

  
Before diving into the Spring Framework, it’s helpful to first understand what a POJO is, and then gradually move on to other topics — this way, everything will make more sense.  
  
A **POJO** (Plain Old Java Object) is a simple class that only contains private fields, public getters and setters, and sometimes constructors. It doesn't extend any special classes or implement specific interfaces — it's just a "plain" object used to store and transfer data.  

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1745813514808/a77de4db-2158-45bf-858d-1570f89ab522.png align="center")

```plaintext
public class Person {
    private String name;
    private int age;

    // Constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter and Setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
```

---

In the above code the constructor initializes object attributes at creation, while getters and setters allow reading and updating those attributes later.  
  
Now, let's understand the concepts of Tightly Coupled and Loosely Coupled.  

| **Tightly Coupled** | **Loosely Coupled** |
| --- | --- |
| Objects are heavily dependent on each other. | Objects are independent and interact with minimal dependency. |
| Hard to modify or test individual components. | Easy to modify, test, and maintain code. |
| Changing one class often affects others. | Changing one class usually doesn't impact others. |

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1745813705653/0904b477-d421-44b2-b353-7b8aafc27233.png align="center")

Tightly coupled example.

```plaintext
class Engine {
    void start() {
        System.out.println("Engine started");
    }
}

class Car {
    Engine engine = new Engine(); // Direct dependency

    void startCar() {
        engine.start();
    }
}
```

In the tightly coupled example, the `Car` class **creates** its own `Engine` object internally, making it hard to change or replace the `Engine` without modifying the `Car` class itself.  
  
Loosely Coupled example.

```plaintext
class Engine {
    void start() {
        System.out.println("Engine started");
    }
}

class Car {
    Engine engine;

    Car(Engine engine) {  // Engine passed from outside
        this.engine = engine;
    }

    void startCar() {
        engine.start();
    }
}
```

In the loosely coupled example, the `Engine` object is **passed into** the `Car` class from outside (via constructor), making it flexible, easier to test, and maintain without changing the `Car` code.  
  
  
Now, let's dive into Inversion of Control and Dependency Injection.  
  
🔵 **Inversion of Control (IoC):**

**IoC means giving control of creating and managing objects to someone else (like a framework), instead of the program handling it directly.**  
  
  
🔵 **Dependency Injection (DI)**:

> DI is a way to implement IoC where the required objects (dependencies) are given to a class from outside, rather than the class creating them itself.  
>   
> **Super Short Summary**:
> 
> > IoC = "Don't call us, we’ll call you."  
> > DI = "I'll hand you what you need."  
> > 
> >   
> > **Real-world Example:**
> > 
> > * **Without IoC (Manual way):**  
> >     You **go to the kitchen**, find ingredients, cook the food, and then eat.  
> >     → You are doing **everything yourself** (full control).  
> >     
> > * **With IoC and DI:**  
> >     You **order food** from a restaurant (like Swiggy or Zomato 🍔🚚).  
> >     The restaurant prepares the food and **delivers** it to you.  
> >     You just **eat** — you don’t worry about cooking or ingredients!
> >     

  
In a typical object-oriented design, classes often depend on other classes to function. Traditionally, we instantiate these dependent classes manually inside our design class, which leads to **tight coupling** and makes the system hard to test and maintain.

However, with Spring, we leverage **Inversion of Control (IoC)**, where the control of object creation and dependency management is transferred to the **Spring IoC container**. This container automatically handles the **instantiation**, **configuration**, and **lifecycle** of dependent objects through **Dependency Injection (DI)**. As a result, our code becomes **loosely coupled**, more **modular**, and **easier to test and maintain.**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1745813937261/dd54b083-d368-4b23-9648-557d7bf7003b.png align="center")

---

```plaintext
class Food {
    void prepare() {
        System.out.println("Cooking food...");
    }
}

class Person {
    Food food = new Food();  // Person makes the food themselves

    void eat() {
        food.prepare();
        System.out.println("Eating food");
    }
}
```

👉 Here, `Person` is tightly coupled to `Food`.  
They **create** and **prepare** the food themselves!

---

```plaintext
class Food {
    void prepare() {
        System.out.println("Food prepared and delivered!");
    }
}

class Person {
    Food food;

    // Food is injected (maybe by a delivery guy! 😄)
    Person(Food food) {
        this.food = food;
    }

    void eat() {
        food.prepare();
        System.out.println("Eating delivered food");
    }
}
```

```plaintext
public class Main {
    public static void main(String[] args) {
        Food orderedFood = new Food();  // Food prepared somewhere
        Person person = new Person(orderedFood);  // Injecting food
        person.eat();  // Just eating!
    }
}
```

✅ **Summary:**

* **Without IoC** = You prepare your own food (tight coupling).
    
* **With IoC and DI** = Someone else prepares food and gives it to you (loose coupling).
    

---

🔵 **Bean in Java (especially in Spring):**

> A **Bean** is a **simple Java object** that is **managed** by a framework like **Spring** — it is created, configured, and injected automatically by the framework.
> 
> ---
> 
> **Simple words:**
> 
> > A bean = a Java object that Spring creates and manages for you.
> > 
> > ---

```plaintext
@Component
class Food {
    // Food class becomes a Bean
}
```

  
🔵 **ApplicationContext in Spring:**

> **ApplicationContext** is the **container** in Spring that **manages all the Beans** — it creates them, wires them together, configures them, and handles their entire lifecycle.  
>   
> **Simple words:**
> 
> > It’s like Spring’s **brain** that knows **which objects (Beans)** exist and **how they should be connected**.  
> >   

```plaintext
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Food food = context.getBean(Food.class);
```

Here, the `context` manages and gives you the `Food` Bean! in a java configuration file mention below.

---

```plaintext
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public Food food() {
        return new Food();
    }
}
```

✅ **Explanation:**

* `@Configuration` → Marks this class as a configuration file for Spring.
    
* `@Bean` → Tells Spring to create and manage a `Food` object as a **Bean**.  
    

With the help of annotations in Spring Boot, our work becomes much easier and more convenient. However, understanding Spring Core is a necessary prerequisite.

Here’s a list of resources that helped me gain a deeper understanding of Spring Core.  
  
[https://www.youtube.com/watch?v=KcJ2mAYfjxU&list=PLhHaibdHQVE3EHm3w0r38x9oxESLbg-TV](https://www.youtube.com/watch?v=KcJ2mAYfjxU&list=PLhHaibdHQVE3EHm3w0r38x9oxESLbg-TV)  
  
And of course, Telusko’s videos, which tie everything together perfectly.  
  
[https://www.youtube.com/watch?v=If1Lw4pLLEo&t=2145s](https://www.youtube.com/watch?v=If1Lw4pLLEo&t=2145s)  
  
Thank you and Happy Learning :)
