Skip to main content

Dependency Injection & Bean Creation Deep Dive

Dependency Injection & Bean Creation Deep Dive

To truly master the Spring Framework and Spring Boot, you must understand exactly how it manages objects, resolves dependencies, and orchestrates its internal startup flow. Let's break down the core architectural concepts of Dependency Injection and Bean Creation.


1. What is a Bean?

Standard Definition

A Bean is an object that is created, managed, configured, and destroyed by the Spring IOC Container.

Consider a standard Java object:

public class EmployeeService { } // Normal Java Object (NOT a Spring Bean) EmployeeService service = new EmployeeService();

However, when Spring creates it, it becomes a Spring Bean:

@Service public class EmployeeService { }

What does "Managed by Spring" mean?

When an object is managed by Spring, the framework automatically handles:

  • Object Creation
  • Dependency Injection
  • Initialization
  • Configuration
  • Lifecycle Management
  • Destruction

Without Spring (Manual Creation):

EmployeeRepository repo = new EmployeeRepository(); EmployeeService service = new EmployeeService(repo);

With Spring (Automatic Management):

@Service public class EmployeeService { private final EmployeeRepository repo; public EmployeeService(EmployeeRepository repo) { this.repo = repo; } }

Spring automatically creates both objects and wires them together.


2. What is the IOC Container?

IOC stands for Inversion of Control.

In traditional Java, the developer controls object creation (using the new keyword). In Spring, the framework creates the objects. Control moves from the Developer → Spring. Hence, "Inversion of Control."

IOC Container Internals

The main container interface is the ApplicationContext. Some concrete implementations include:

  • AnnotationConfigApplicationContext
  • ClassPathXmlApplicationContext
  • WebApplicationContext

In Spring Boot, the ApplicationContext is automatically created for you.

Internal Startup Flow

SpringApplication.run() | V Create ApplicationContext | V Component Scan | V Find Bean Classes | V Create Bean Definitions | V Register Bean Definitions | V Instantiate Beans | V Inject Dependencies | V Store Beans in IOC Container | V Application Ready

3. What is a Bean Definition?

Before creating an actual object, Spring parses your class and creates metadata.

@Service public class EmployeeService { }

Spring translates this into metadata called a BeanDefinition:

  • Bean Name: employeeService
  • Class: EmployeeService
  • Scope: Singleton
  • Dependencies: EmployeeRepository

Internal Flow of Metadata

@Component | V ClassPath Scanner | V BeanDefinition | V BeanFactory | V Object Creation

4. The Bean Creation Process

Let's look at exactly how Spring creates a bean internally in 5 steps:

  1. Scan Package: @ComponentScan detects the class.
  2. Create BeanDefinition: Spring creates metadata.
  3. Register Metadata: Registers the definition into the BeanDefinitionRegistry.
  4. Instantiate Object: Spring creates the actual object using Reflection.
    Class<?> clazz = EmployeeService.class; Object obj = clazz.getDeclaredConstructor().newInstance();
  5. Store in Cache: Stores the bean inside the singleton cache (singletonObjects inside DefaultSingletonBeanRegistry).

The Internal Cache Structure

singletonObjects | +---- employeeService | +---- employeeRepository | +---- dataSource

5. What is Dependency Injection?

Standard Definition

Dependency Injection is a design pattern where Spring provides required dependencies to an object instead of the object creating them itself.

Without DI (Tightly coupled):

public class EmployeeService { EmployeeRepository repo = new EmployeeRepository(); }

With DI (Loosely coupled):

public class EmployeeService { private EmployeeRepository repo; public EmployeeService(EmployeeRepository repo) { this.repo = repo; } }

6. Types of Dependency Injection

1. Constructor Injection (Recommended)

The safest and most modern approach. Ensures immutable dependencies.

@Service public class EmployeeService { private final EmployeeRepository repo; public EmployeeService(EmployeeRepository repo) { this.repo = repo; } }

Flow: Create Repository Bean → Create Service Bean → Pass Repository → Constructor Injection.

2. Setter Injection

@Autowired public void setRepo(EmployeeRepository repo) { this.repo = repo; }

3. Field Injection (Not Recommended)

@Autowired private EmployeeRepository repo;

7. How Dependency Injection Works Internally

When Spring creates EmployeeService, it sees that EmployeeRepository is required. It searches the IOC container. If found, it injects it.

Create EmployeeRepository | V Store in Container | V Create EmployeeService | V Need Repository? | V Get Bean from Container | V Inject Dependency

8. Deep Dive into Stereotype Annotations

@Component

A generic Spring Bean. Internally, it triggers the ClassPathBeanDefinitionScanner to create a BeanDefinition and instantiate the bean.

@Service

A specialized @Component representing the Business Logic Layer. Internally, @Service is meta-annotated with @Component. It carries semantic meaning for developers.

@Repository

Represents the DAO Layer. Internally, it is also a @Component, but it provides a massive extra feature: Exception Translation.

If the database throws a raw SQLException, the PersistenceExceptionTranslationPostProcessor catches it at the repository layer and translates it into Spring's database-independent DataAccessException hierarchy.

@Controller

Used in Spring MVC. It specifically returns a View Name, which is processed by the ViewResolver to return JSP or HTML.

@RestController

Used for REST APIs. It returns raw data (JSON) directly to the response body.

Internally, @RestController = @Controller + @ResponseBody.

Request -> Controller -> Java Object -> Jackson -> JSON -> Response

9. Java Configuration: @Configuration & @Bean

Before Spring Boot, everything was configured via XML (<bean id="employeeService"/>). Modern Spring uses Java Configuration.

@Configuration

Marks a class as a configuration source containing bean definitions. Internally, it is meta-annotated with @Component, allowing Spring to detect it during a component scan.

@Bean

Used to create beans manually. Spring registers the returned object as a bean in the container.

@Configuration public class AppConfig { @Bean public EmployeeService employeeService() { return new EmployeeService(); } }

Why is @Bean needed?
If a class belongs to a third-party library (e.g., PaymentGateway), you cannot modify its source code to add @Component. You must use @Bean to instantiate and configure it manually.


10. @Component vs @Bean (Interview Favorite)

Feature @Component @Bean
Applied On Class Method
Bean Creation Automatic Manual
Scanning Required Yes No
Third Party Class No Yes
Uses Component Scan Yes No
Control Level Less More (Custom Initialization)

When to use @Component? When you own the source code (Service, DAO, Controller utility classes).

When to use @Bean? For third-party library classes, custom initialization logic, or creating multiple bean instances.


11. Complete Internal Flow of Dependency Injection

SpringApplication.run() | V ApplicationContext Created | V @ComponentScan | V Find Classes | V Create BeanDefinition | V Register BeanDefinition | V Instantiate Beans | V Constructor Dependency Analysis | V Find Required Beans | V Resolve Dependencies | V Inject Dependencies | V Store Beans in Singleton Cache | V Application Ready

12. Interview Summary & Key Takeaways

Core Concepts

  • What is Dependency Injection? A mechanism where Spring provides required dependencies to an object instead of the object creating them manually.
  • What is a Bean? An object created, managed, and maintained by the Spring IOC Container.
  • @Component vs @Bean: @Component is for automatic bean creation via scanning. @Bean is for manual bean creation via a method inside a @Configuration class.
  • @Service vs @Repository vs @Component: All are Spring beans based on @Component. @Service signifies business logic. @Repository signifies data access and adds exception translation.
  • @Controller vs @RestController: @Controller returns a View (JSP/HTML). @RestController returns raw data (JSON/XML) directly.
  • Why Constructor Injection? It ensures immutable dependencies, makes unit testing easier, prevents NullPointerExceptions, and is officially recommended by the Spring team.

Internal Classes You Must Know

To demonstrate a senior-level understanding, familiarize yourself with these backend classes:

  • ApplicationContext
  • BeanFactory
  • BeanDefinition
  • BeanDefinitionRegistry
  • ClassPathBeanDefinitionScanner
  • DefaultListableBeanFactory
  • DefaultSingletonBeanRegistry
  • AutowiredAnnotationBeanPostProcessor
  • ConfigurationClassPostProcessor

Comments

Popular posts from this blog

How I Got Selected in MNC

Virtusa Sometimes success does not come from having the best coding skills or the perfect roadmap. Sometimes it comes from simply refusing to quit. This is the honest story of how I transitioned from a confused, rejected fresher to getting selected as an Associate Engineer at Virtusa. The Beginning: Confused About My Future After completing my graduation, I stared blankly at my career options. Like many freshers, I lacked a clear direction. Should I join a Java course? Should I prepare on my own? Should I just wait for campus placement opportunities? One day, I called my friend Chetan. He suggested I join Naresh i Technologies and start learning Java seriously. Still unsure of my path, I told him I needed time to think about it. A couple of days later, my phone buzzed with a WhatsApp message offering a job opportunity. They asked me to come for the next round of the recruitment process. Excitement completely took over. I packed my bags, traveled to th...

Spring Boot Introduction

Spring Boot Introduction: Architecture, Dependencies, and Embedded Servers Modern enterprise applications demand rapid development, frictionless deployment, and absolute minimal configuration. Before Spring Boot arrived, developers utilizing the Spring Framework wasted immense amounts of time configuring XML files, managing clashing dependencies, setting up clunky application servers, and stitching various Spring modules together manually. To eliminate these bottlenecks, Pivotal introduced Spring Boot . Built entirely on top of the traditional Spring Framework, Spring Boot is an "opinionated" framework. It aggressively simplifies application development by injecting auto-configuration, packaging starter dependencies, and embedding web servers directly into your application. This allows backend developers to focus entirely on building business logic rather than wrestling with infrastructure setup. What is Spring Boot? Spring Boot is a powerful extens...

Strings in C

C Programming: Working with Strings Unlike modern programming languages like Python or Java, C does not possess a dedicated "String" data type. Instead, C treats a string as a simple 1D array of characters. Real-life example: Think of a freight train. The train does not exist as one solid object; it consists of individual boxcars linked together. Similarly, a C string links individual characters side-by-side in memory. To let the computer know the train has ended, C attaches a special "caboose" called the Null Terminator ( \0 ). 1. Essential String Functions Handling strings manually requires complex loops. To save time, C provides a built-in library called <string.h> that contains powerful functions to manipulate text. strlen(): You use this to find the exact length of a string. The compiler counts the characters until it hits the \0 terminator. It does not count the terminator itself. strcpy(): You ...