What Is Spring Framework and How Does Dependency Injection Work?

Spring Framework Tutorial for Beginners is an essential read for anyone diving into Java development. Understanding this framework can solve common challenges like dependency injection and streamline your application’s architecture. Keen to create more efficient, dynamic applications? Let’s demystify this powerful tool together and boost your programming skills. Keep reading!

What Is Spring Framework?

Definition

Spring Framework is a powerful, open-source Java framework used to build enterprise-level applications. It provides comprehensive infrastructure support for developing Java applications in a simple, flexible, and modular way.

In simple terms, Spring helps developers build Java applications faster by handling common tasks like object creation, configuration, and dependency management.

Open-Source Framework

Spring is completely open-source and maintained by the community and VMware. Because it is open-source:

  • Developers can use it for free
  • It has strong community support
  • It receives regular updates
  • Thousands of libraries and integrations are available

This makes Spring one of the most trusted frameworks in enterprise Java development.

Lightweight & Modular Architecture

Spring is considered lightweight because:

  • It does not force developers to use heavy configurations
  • It supports POJO-based programming
  • You can use only the modules you need

Spring follows a modular architecture. It is divided into different modules such as:

  • Spring Core
  • Spring AOP
  • Spring MVC
  • Spring JDBC
  • Spring Security
  • Spring Boot

You can choose only the required modules instead of loading everything.

POJO-Based Development

POJO stands for Plain Old Java Object.

Spring allows you to write simple Java classes without forcing you to extend special framework classes. This makes your code:

  • Cleaner
  • Easier to test
  • Less tightly coupled
  • More maintainable

Unlike older frameworks, Spring does not require complex inheritance structures.

Core Features of Spring Framework

Spring provides several powerful features that make it widely used in enterprise applications.

Inversion of Control (IoC)

Inversion of Control means that the control of object creation and management is transferred from the developer to the Spring container.

Instead of creating objects manually using new, Spring creates and manages them for you.

This reduces tight coupling and improves flexibility.

Dependency Injection (DI)

Dependency Injection is a design pattern implemented by Spring to achieve loose coupling.

It means that dependencies required by a class are provided by the Spring container instead of being created inside the class.

This improves:

  • Code reusability
  • Testability
  • Maintainability

Aspect-Oriented Programming (AOP)

AOP allows you to separate cross-cutting concerns such as:

  • Logging
  • Security
  • Transaction management

Instead of writing logging code in every method, AOP allows you to define it separately and apply it wherever needed.

This keeps business logic clean.

Spring MVC

Spring MVC is a web module used to build web applications and REST APIs.

It follows the Model-View-Controller architecture, which separates:

  • Model → Business logic
  • View → UI
  • Controller → Request handling

Spring MVC makes it easy to develop scalable and maintainable web applications.

Spring Boot Overview

Spring Boot is an extension of the Spring Framework that simplifies configuration.

It provides:

  • Auto-configuration
  • Embedded servers (Tomcat, Jetty)
  • Production-ready features
  • Minimal setup

With Spring Boot, you can build applications much faster compared to traditional Spring setup.

Basic Concepts of Spring Framework

Understanding the basic concepts is essential for beginners learning Spring Framework.

🔹 Inversion of Control (IoC)

What Is IoC?

Inversion of Control is a principle where the control of object creation and lifecycle management is handled by the Spring container instead of the developer.

Traditionally, developers create objects manually. In Spring, the container manages them.

Traditional Object Creation vs Spring-Managed Objects

Traditional Approach:

Car car = new Car();
Engine engine = new Engine();
car.setEngine(engine);

Here, the developer manually creates and connects objects.

Spring Approach:

Spring container creates objects (beans) and injects dependencies automatically.

This reduces tight coupling and makes the code flexible.

🔹 Bean

What Is a Bean?

In Spring, a Bean is simply an object that is created, configured, and managed by the Spring IoC container.

Any class that is registered in the Spring container becomes a bean.

Bean Lifecycle

The lifecycle of a Spring Bean includes:

  1. Bean Instantiation
  2. Dependency Injection
  3. Initialization
  4. Bean Ready for Use
  5. Destruction (when container shuts down)

Spring manages this entire lifecycle automatically.

🔹 ApplicationContext

Role of IoC Container

The IoC container is responsible for:

  • Creating beans
  • Injecting dependencies
  • Managing bean lifecycle
  • Handling configuration

The most commonly used container is ApplicationContext.

BeanFactory vs ApplicationContext

BeanFactoryApplicationContext
Basic containerAdvanced container
Lazy initializationEager initialization
Limited featuresSupports AOP, events, internationalization

ApplicationContext is more powerful and commonly used in modern applications.

What Is Dependency Injection in Spring?

Definition of Dependency Injection

Dependency Injection (DI) is a design pattern where objects receive their dependencies from an external source rather than creating them internally.

In Spring, the IoC container injects dependencies into beans automatically.

Why DI Is Important

Dependency Injection helps:

  • Reduce tight coupling
  • Improve code readability
  • Simplify testing
  • Increase flexibility

It allows you to change implementation without modifying the main class.

Problems Without DI

Without Dependency Injection:

  • Classes create their own dependencies
  • Code becomes tightly coupled
  • Testing becomes difficult
  • Changes require modifying multiple classes

Example without DI:

class Car {
    Engine engine = new Engine();
}

Here, Car is tightly coupled with Engine.

Real-World Example Explanation

Imagine a Car that depends on an Engine.

Without DI → Car creates its own Engine.
With DI → Engine is provided to Car by Spring.

This means:

  • You can easily replace PetrolEngine with DieselEngine
  • No need to modify Car class
  • Better flexibility and scalability

This is why Dependency Injection is one of the most powerful features of the Spring Framework.

Types of Dependency Injection

Spring Framework mainly supports three types of Dependency Injection:

  • Constructor Injection
  • Setter Injection
  • Field Injection

Let’s understand each one clearly.

✅ Constructor Injection

Constructor Injection means dependencies are provided through the class constructor.

In this type, the required objects are passed as parameters when the object is created.

Example Explanation

@Component
class Engine {
    public String start() {
        return "Engine Started";
    }
}

@Component
class Car {

    private Engine engine;

    @Autowired
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        System.out.println(engine.start());
    }
}

Here:

  • Engine is a dependency.
  • Car receives Engine through its constructor.
  • Spring automatically injects the Engine object when creating Car.

When to Use Constructor Injection

Constructor Injection is recommended when:

  • The dependency is mandatory.
  • The object cannot function without the dependency.
  • You want to create immutable classes (no setter methods).
  • You want better unit testing.

It is considered the best practice in modern Spring applications.

✅ Setter Injection

Setter Injection means dependencies are injected using setter methods.

Spring first creates the object using the default constructor, then calls the setter method to inject the dependency.

Example Explanation

@Component
class Car {

    private Engine engine;

    @Autowired
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        System.out.println(engine.start());
    }
}

Here:

  • Spring creates the Car object.
  • Then it calls setEngine() method.
  • The dependency is injected after object creation.

When to Use Setter Injection

Setter Injection is useful when:

  • The dependency is optional.
  • You want flexibility to change dependency later.
  • You do not want the dependency to be mandatory.

However, it is not ideal for required dependencies because the object can exist without them.

✅ Field Injection (Brief)

Field Injection means dependencies are injected directly into class fields.

Example

@Component
class Car {

    @Autowired
    private Engine engine;

    public void drive() {
        System.out.println(engine.start());
    }
}

Here:

  • No constructor.
  • No setter method.
  • Spring injects the dependency directly into the field.

Pros of Field Injection

  • Simple and less code.
  • Easy to write.
  • Clean looking class.

Cons of Field Injection

  • Harder to test (cannot easily mock dependencies).
  • Not recommended for large applications.
  • Creates hidden dependencies.
  • Cannot create immutable objects.

For these reasons, Constructor Injection is preferred over Field Injection in professional applications.

How Dependency Injection Works Internally

Now let’s understand what happens behind the scenes when Spring injects dependencies.

Role of IoC Container

The IoC (Inversion of Control) container is the core of the Spring Framework.

Its responsibilities include:

  • Creating objects (beans)
  • Managing bean lifecycle
  • Injecting dependencies
  • Handling configurations

The most commonly used IoC container is ApplicationContext.

When the application starts:

  1. Spring scans for components (like @Component, @Service, @Repository)
  2. It creates objects for those classes.
  3. It manages them inside the container.

Bean Creation Process

Here is the simplified step-by-step process:

1️⃣ Spring reads configuration (XML, Java config, or annotations).
2️⃣ It scans the classpath for annotated classes.
3️⃣ It creates bean objects.
4️⃣ It injects dependencies (using constructor, setter, or field).
5️⃣ It calls initialization methods.
6️⃣ The bean is ready to use.

When the application shuts down, Spring destroys the beans properly.

Wiring Dependencies

Wiring means connecting one bean with another.

Example:

  • Car depends on Engine.
  • Spring identifies this dependency.
  • It injects Engine into Car automatically.

This process is called Autowiring.

Spring resolves dependencies by:

  • Type
  • Name
  • Qualifier annotation (if multiple beans exist)

Example:

@Autowired
private Engine engine;

Spring searches for a bean of type Engine and injects it.

What Happens Behind the Scenes?

Internally:

  • Spring uses Reflection to create objects.
  • It maintains a bean definition map.
  • It checks dependencies before object creation.
  • It ensures singletons are reused (by default).

By default, Spring beans are Singleton scoped, meaning only one instance is created per container.

Why This Internal Mechanism Is Powerful

Because Spring handles object creation and wiring:

  • Developers focus only on business logic.
  • Code becomes loosely coupled.
  • Testing becomes easier.
  • Applications become scalable and maintainable.

Spring Framework Basics

java
package com.example.springtutorial;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

// Step 1: Create a simple service interface
interface GreetingService {
    String sayGreeting();
}

// Step 2: Implement the service with a component annotation
@Component
class GreetingServiceImpl implements GreetingService {
    public String sayGreeting() {
        return "Hello, welcome to the Spring Framework!";
    }
}

// Step 3: Create a controller class that uses the service
@Component
class GreetingController {
    private GreetingService greetingService;

    @Autowired
    public void setGreetingService(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    public void greet() {
        System.out.println(greetingService.sayGreeting());
    }
}

// Step 4: Create a configuration class with component scanning
@Configuration
@ComponentScan("com.example.springtutorial")
class AppConfig {
    @Bean
    public GreetingService greetingService() {
        return new GreetingServiceImpl();
    }
}

// Step 5: Finally, create a main class to run the application
public class SpringTutorialApplication {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        GreetingController controller = context.getBean(GreetingController.class);
        controller.greet();
    }
}
  

Explanation of the Code

Understanding how this Spring Framework code works can be a little daunting at first, but let’s break it down step-by-step and make it simpler.

  1. First, there’s an interface named `GreetingService`. Think of it as a promise that any class implementing it will provide a method called `sayGreeting`, which returns a message.
  2. Then comes `GreetingServiceImpl`, a class doing exactly that. It implements the `GreetingService` and once you call `sayGreeting`, it cheerfully replies, “Hello, welcome to the Spring Framework!” Notice the use of `@Component`, which tells Spring to manage this class as a Spring bean.
  3. We’ve got the `GreetingController`, an interesting piece as it uses `GreetingService`. Here’s where dependency injection pops in via `@Autowired`, meaning Spring automatically wires in `GreetingServiceImpl` when needed.
  4. The `AppConfig` class is decorated with `@Configuration` and `@ComponentScan`. It instructs Spring on where to find the beans and define them.
  5. Finally, the `main` method in `SpringTutorialApplication` bootstraps the application, greets using `GreetingController`, bringing the magic to life!

Output

Hello, welcome to the Spring Framework!

Practical Uses of Spring Framework for Beginners


  1. E-commerce Platform Development at Amazon
    Amazon uses the Spring Framework for building robust and scalable e-commerce platforms. By implementing dependency injection, they ensure that different components of their application can be easily managed and scaled. Here’s a simple code snippet showcasing how a service might be wired into a controller:
      
    @Service
    public class ProductService {
    public String getProductDetails() {
    return "Product details for Amazon";
    }
    }

    @Controller
    public class ProductController {
    @Autowired
    private ProductService productService;

    public void displayProduct() {
    System.out.println(productService.getProductDetails());
    }
    }

    *Output*: By using Spring, Amazon achieves seamless integration of microservices, which results in faster loading times and easier maintenance of their platform.


  2. Online Banking Applications at HSBC
    HSBC utilises Spring Framework for its online banking services to ensure security and efficient processing of transactions. Dependency injection helps manage user authentication and transaction services more effectively.
      
    @Component
    public class AuthService {
    public boolean authenticate() {
    return true;
    }
    }

    @Service
    public class BankService {
    @Autowired
    private AuthService authService;

    public void processTransaction() {
    if(authService.authenticate()) {
    System.out.println("Transaction processed by HSBC");
    } else {
    System.out.println("Authentication failed");
    }
    }
    }

    *Output*: The result is a secure, reliable banking application that can handle a high volume of transactions daily.

Advantages of Using Spring Framework

Spring Framework is widely adopted in enterprise applications because it provides multiple architectural and development advantages. Below are the key benefits that make Spring a preferred choice for Java developers.

1. Loose Coupling

Loose coupling means that classes are independent of each other.

In traditional Java applications, classes often create their own dependencies using the new keyword. This creates tight coupling, where one class directly depends on another.

Spring solves this problem using:

  • Inversion of Control (IoC)
  • Dependency Injection (DI)

Instead of creating dependencies internally, Spring injects them from the outside.

Why Loose Coupling Is Important

  • You can replace one implementation with another easily.
  • Changes in one class do not affect other classes.
  • Code becomes flexible and reusable.

For example, if a Car class depends on an Engine, you can switch from PetrolEngine to DieselEngine without modifying the Car class.

This makes applications more adaptable to change.

2. Easier Testing

Spring Framework makes unit testing much easier.

Because dependencies are injected externally:

  • You can replace real dependencies with mock objects.
  • You can test individual components independently.
  • You don’t need the full application to test one class.

Spring also integrates well with:

  • JUnit
  • Mockito
  • TestNG

Constructor Injection especially improves testability because you can manually pass mock dependencies during testing.

This leads to:

  • Faster debugging
  • Better code quality
  • More reliable applications

3. Better Maintainability

Spring promotes clean architecture and separation of concerns.

With features like:

  • Dependency Injection
  • Aspect-Oriented Programming (AOP)
  • Modular design

Your code becomes:

  • Organized
  • Easy to understand
  • Easy to update

For example:

  • Logging logic can be separated using AOP.
  • Business logic remains clean.
  • Configuration is centralized.

When the project grows, developers can maintain and update it without breaking existing functionality.

4. Scalable Architecture

Spring is designed to build enterprise-level applications.

It supports:

  • Microservices architecture
  • Cloud deployment
  • RESTful APIs
  • Distributed systems

With Spring Boot and Spring Cloud, developers can easily build scalable and production-ready systems.

Spring applications can:

  • Handle high traffic
  • Integrate with databases
  • Connect with messaging systems
  • Deploy in containers like Docker and Kubernetes

This makes Spring suitable for:

  • Banking systems
  • E-commerce platforms
  • SaaS applications
  • Large enterprise systems

Why Companies Prefer Spring

Due to loose coupling, easier testing, maintainability, and scalability, Spring Framework is trusted by global organizations for building secure and high-performance applications.

It allows teams to develop faster while maintaining clean and professional code structure.

Ace Spring Framework Tutorial for Beginners Interviews


  1. What is the Spring Framework and why is it so popular?
    The Spring Framework is a comprehensive framework for building Java applications. It’s popular because it simplifies the development process by offering extensive functionalities like dependency injection, aspect-oriented programming, and more. It makes Java development faster and more efficient.
  2. How does dependency injection work in Spring?
    Dependency injection in Spring is a design pattern that allows objects to be created outside of a class and injected into it. This promotes loose coupling and enhances the testability. Spring can do this automagically through constructor-based or setter-based injection. Here’s a simple example:

    public class Car {
    private Engine engine;
    public Car(Engine engine) {
    this.engine = engine;
    }
    }
  3. What is the significance of the @Autowired annotation in Spring?
    The @Autowired annotation in Spring allows the framework to resolve and inject collaborating beans into our bean. When it’s used, Spring’s magic comes into play, automatically taking care of the necessary object creation and injection.
  4. Can you explain what a Spring Bean is?
    A Spring Bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Spring Beans are the backbone of any Spring-driven application and are defined in the configuration metadata, either by XML or annotations.
  5. What are some real-world applications of the Spring Framework?
    The Spring Framework is used in various applications, from web apps to enterprise-level software systems. Companies use it for building scalable, reliable backend services, microservices, and cloud-based applications due to its flexibility and ease of use.

Experience the future of coding with our AI-powered Java online compiler. Instantly write, run, and test your code, harnessing the power of AI for real-time feedback and enhanced learning. Dive into seamless coding with minimal effort, letting technology streamline your programming journey and bring your Java projects to life.

Conclusion

Completing the ‘Spring Framework Tutorial for Beginners’ equips you with essential skills to build robust Java applications efficiently. You’ll feel a rewarding sense of accomplishment, motivated to explore more. Discover additional programming languages like Java, Python, C, and C++ at Newtum. Dive in and elevate your coding expertise!

Edited and Compiled by

This article was compiled and edited by @rasikadeshpande, who has over 4 years of experience in writing. She’s passionate about helping beginners understand technical topics in a more interactive way.

About The Author