Lecture 25: Spring Core Basics & Dependency Injection

BMC201 - Web Technology

Mr. Prashant Kumar Nag

2026-03-09

Lecture 25

Spring Core Basics & Dependency Injection

Week 7 | Unit IV: Spring Framework Basics
BMC201 - Web Technology
Mr. Prashant Kumar Nag, Assistant Professor

Learning Objectives


  • Define Spring Framework and explain what it is
  • List key advantages of Spring for enterprise development
  • Summarize the history and evolution of Spring
  • Explain Spring Core motivation
  • Understand dependency injection
  • Compare tight coupling vs DI

Prerequisites


  • Core Java OOP concepts and interface-based design
  • Basic understanding of Servlets/JSP request flow from Unit III
  • Revision of Lecture 24 before moving into Spring Core Basics & Dependency Injection

Syllabus Mapping


  • Unit IV topic focus: Spring Core Basics & Dependency Injection
  • CO alignment: implementation understanding + architecture reasoning
  • Assessment alignment: short definitions + long implementation/design questions

Agenda


  • 5-minute recap from previous lecture
  • Concept deep dive: Spring Core Basics & Dependency Injection
  • Code/configuration walkthrough and output analysis
  • Debug checklist and exam-oriented summary

Introduction


Spring Core is the foundation of the Spring ecosystem and focuses on one major goal:

  • move object creation and wiring out of business classes
  • centralize dependency management in the IoC container
  • keep application modules loosely coupled and easier to test

In practical system design, service classes remain focused on business logic while the container manages creation and wiring of dependencies. This separation improves maintainability, testability, and long-term change readiness.

Definition of Spring


Spring Framework is an open-source Java framework used to build enterprise applications in a modular, testable, and maintainable way.

At its core, Spring provides:

  • Inversion of Control (IoC) for object lifecycle management
  • Dependency Injection (DI) for loose coupling between components
  • consistent programming model for web, data, security, and microservices

What Spring Is


Think of Spring as an application framework + ecosystem.

  • It is not just one library; it is a family of projects
  • Spring Core provides IoC container and bean wiring
  • Spring MVC supports web applications and REST APIs
  • Spring Boot simplifies setup, configuration, and deployment

In one line: Spring lets developers focus on business logic while the framework handles infrastructure concerns.

History of Spring


Quick timeline:

  • 2002: Rod Johnson publishes ideas that challenge heavyweight J2EE development
  • 2003: Spring Framework appears as a lightweight alternative for enterprise Java
  • 2004: Spring 1.0 release, strong adoption for IoC and DI
  • 2014: Spring Boot launch simplifies production-ready app development
  • Today: Spring ecosystem powers cloud-native apps, microservices, and enterprise platforms

Advantages of Spring


Key advantages in real projects:

  • Loose coupling: DI keeps business classes independent of concrete implementations
  • Better testability: dependencies can be replaced with mocks/stubs in unit tests
  • Modular architecture: choose only required modules (Core, MVC, Data, Security)
  • Faster development: Spring Boot reduces setup and boilerplate configuration
  • Production readiness: built-in support for monitoring, profiles, and externalized config
  • Strong ecosystem: large community, documentation, and enterprise adoption

Exam line: Spring improves maintainability, scalability, and development speed through IoC, DI, and ecosystem support.

Think About It


Key design questions for dependency injection:

  1. If OrderService creates new UpiGateway(), what happens when business asks for CardGateway tomorrow?
  2. How will you unit test OrderService if dependency creation is hardcoded inside it?
  3. Who should own object lifecycle: each class or a container?
  4. Which design is easier to maintain after 6 months: direct object creation or DI-based wiring?

Key reflection: externalizing object creation reduces coupling, improves testability, and keeps business classes focused.

Why Spring Core Was Needed


In large Java projects without a container:

  • classes create dependencies directly using new
  • switching implementation forces code changes in business classes
  • unit testing becomes difficult because real dependencies are tightly bound
  • object graph wiring logic gets repeated across modules

Spring Core solves this with IoC + DI

Tight Coupling vs Dependency Injection


Tight Coupling (without DI)

class OrderService {
  private final PaymentGateway gateway = new UpiGateway();
}
  • hard to replace implementation
  • hard to mock in tests
  • violates separation of concerns

Loose Coupling (with DI)

class OrderService {
  private final PaymentGateway gateway;
  OrderService(PaymentGateway gateway){ this.gateway = gateway; }
}
  • implementation selected externally
  • easy test doubles/stubs
  • cleaner architecture

Types of Dependency Injection


Main DI styles in Spring:

  1. Constructor Injection (recommended default)
  2. Setter Injection (optional dependencies)
  3. Field Injection (quick but less testable)
// Constructor Injection (preferred)
public OrderService(PaymentGateway gateway) { this.gateway = gateway; }

// Setter Injection
public void setGateway(PaymentGateway gateway) { this.gateway = gateway; }

What IoC Container Actually Does


flowchart TD
  A["Read Configuration / Component Scan"] --> B["Create Bean Definitions"]
  B --> C["Instantiate Beans"]
  C --> D["Resolve Dependencies"]
  D --> E["Inject Dependencies"]
  E --> F["Ready Application Context"]

  • container owns object creation lifecycle
  • application code asks for abstractions, not concrete classes
  • dependency graph is resolved once and reused

What This IoC Figure Means in Practice


  • Read Configuration / Scan: container identifies which classes should be managed.
  • Create Bean Definitions: metadata is prepared for each managed object.
  • Instantiate Beans: container creates required objects at startup (or lazily).
  • Resolve + Inject Dependencies: references are connected in the correct order.
  • Ready Context: application gets a complete object graph before business requests begin.

Presentation takeaway: object wiring is infrastructure work, not business-class responsibility.

What Is a Bean in Spring?


A bean is any object whose full lifecycle is managed by the Spring IoC container.

Bean lifecycle responsibility includes:

  • creation (instantiation)
  • dependency injection
  • initialization callbacks
  • scope handling (singleton, prototype, etc.)
  • destruction callbacks when context closes

Simple definition for exams: A bean is a Spring-managed object stored in the application context.

Dependency Injection Concept


flowchart LR
  C["Client: OrderService"] -->|depends on| A["Abstraction: PaymentGateway"]
  I["Implementation: UpiGateway"] -->|wired by| S["Spring Container"]
  S --> C

  • Business class depends on interface, not concrete implementation
  • Spring container resolves and injects correct dependency
  • This improves testability and reduces coupling

Java Config vs Annotation Scanning


Spring supports multiple ways to register beans:

  • Java Configuration using @Configuration + @Bean
  • Stereotype scanning using @Component, @Service, @Repository

Both lead to the same goal: dependency graph managed by container.

@Service
class OrderService {
  private final PaymentGateway gateway;
  OrderService(PaymentGateway gateway) { this.gateway = gateway; }
}

Code Walkthrough


interface PaymentGateway {}
class UpiGateway implements PaymentGateway {}
class OrderService {
  private final PaymentGateway gateway;
  OrderService(PaymentGateway gateway) { this.gateway = gateway; }
}

@Configuration
class AppConfig {
  @Bean PaymentGateway gateway() { return new UpiGateway(); }
  @Bean OrderService orderService(PaymentGateway gateway) { return new OrderService(gateway); }
}

Walkthrough checkpoints:

  • OrderService never creates gateway directly
  • implementation can be swapped in config only
  • test setup can inject fake gateway without changing business logic

DI in a Layered Application


flowchart TD
  C["Controller"] --> S["Service"]
  S --> R["Repository"]
  R --> D[(Database)]

Dependency Injection helps each layer depend on abstractions:

  • Controller depends on service interface
  • Service depends on repository interface
  • Repository implementation can be replaced without changing service logic

Refactoring from Tight to Loose Coupling


Typical migration sequence:

  1. Extract interface from concrete dependency
  2. Inject interface through constructor
  3. Move implementation selection to Spring configuration
  4. Add alternate implementation (for environment/testing)
  5. Verify behavior without touching business class
interface PaymentGateway { void pay(double amount); }

class CardGateway implements PaymentGateway {
  public void pay(double amount) { /* card flow */ }
}

Unit Testing Advantage of DI


With DI, service testing is isolated from infrastructure:

  • no real payment API call required
  • fake/stub dependency controls test outcomes
  • test failures point to business logic clearly
class FakeGateway implements PaymentGateway {
  boolean called;
  public void pay(double amount) { called = true; }
}

// Inject FakeGateway into OrderService during test

Constructor vs Setter vs Field Injection


Injection Style Best Use Strength Limitation
Constructor Mandatory dependencies Immutable + test-friendly More constructor args if many deps
Setter Optional dependencies Flexible post-creation setup Can leave object partially configured
Field Quick wiring Minimal boilerplate Harder to test and less explicit

Recommended default for production code: Constructor Injection

Common DI Mistakes and Fixes


  1. Direct new inside service classes Fix: inject dependencies through constructor

  2. Using field injection everywhere Fix: prefer constructor injection for required dependencies

  3. Business logic inside configuration classes Fix: keep config only for bean wiring

  4. Circular dependency between services Fix: redesign responsibilities or introduce interface boundary

Memory Booster


Syllabus memory points for Spring Core Basics & Dependency Injection:

  • Core recall: constructor-based DI and inversion of control
  • Exam compare: Tight coupling vs dependency injection
  • Practical anchor: Refactor class to inject dependency via constructor

Live Demo


Live implementation for Spring Core Basics & Dependency Injection:

Open Demo: Lecture 25 - Spring Core Basics & Dependency Injection

Demo flow:

  • Boot IoC container and observe bean wiring trace
  • Switch implementation (UpiGateway -> CardGateway) without changing service code
  • Inject MockGateway to show test-friendly design

Takeaway: configuration changes behavior, business class stays stable.

Resources & References


Structured Debug Checklist


  1. verify the primary API usage for Spring Core Basics & Dependency Injection is correct (imports, method names, config)
  2. check request/bean/session flow and object lifecycle assumptions
  3. inspect server logs for the first exception (not just the final symptom)
  4. reproduce one failing case and one passing case before finalizing fixes

Exam Preparation Questions: Short


  • Define Spring Core Basics & Dependency Injection with one practical use case.
  • Write/identify the key API or construct: constructor-based DI and inversion of control.
  • Differentiate: Tight coupling vs dependency injection.
  • Mention one common implementation error and correction.
  • Why is constructor injection preferred over field injection in production code?

Exam Preparation Questions: Long


  • Explain Spring Core Basics & Dependency Injection with architecture/flow and implementation steps.
  • Write a structured answer comparing two approaches used in this topic.
  • Discuss debugging strategy for this topic with likely failure points.
  • Design a payment module using interface-based DI and justify your bean wiring choices.

Practice Task


  • Implement: Refactor class to inject dependency via constructor.
  • Add console/log output to validate flow step-by-step.
  • Document one bug you encountered and the exact fix.

Checklist


Can you:

  • explain Spring Core Basics & Dependency Injection in your own words?
  • implement a basic example end-to-end?
  • identify and fix one common runtime issue?

Next Lecture


  • Topic: Lecture 26 - Spring IoC & Bean Life Cycle
  • Preparation required: revise this lecture summary and code walkthrough

Questions?

Next: Lecture 26