Spring Beans and Dependency Injection

Spring Beans and Dependency Injection (DI) form the core foundation of the Spring Framework’s Inversion of Control (IoC) engine. Instead of classes creating and managing their own dependencies using the new keyword, the Spring IoC container handles object creation, wiring, lifecycle management, and destruction. This decouples application components, making them modular, reusable, and easy to unit test.

1. Spring Beans

A Spring Bean is any Java object that is instantiated, assembled, and managed by the Spring IoC container.

  • Unlike standard Java objects, beans participate in Spring’s lifecycle hooks (such as initialization and destruction callbacks).
  • They operate under specific scopes—most commonly Singleton (a single shared instance per Spring container, which is the default) or Prototype (a new instance created every time it is requested), alongside web-aware scopes like Request and Session.

2. Dependency Injection

Dependency Injection (DI) is the pattern through which the IoC container supplies required objects (dependencies) to a dependent class at runtime.

  • Constructor Injection: Dependencies are provided via the class constructor (recommended as best practice because it enforces immutability and ensures required dependencies are not null).
  • Setter Injection: Dependencies are injected through public setter methods (ideal for optional dependencies).
  • Field Injection: Uses @Autowired directly on class fields (convenient for prototyping, but generally discouraged in production due to tight coupling and testing difficulties).

3. Component Scanning

Component Scanning is Spring’s automated discovery mechanism for finding and registering beans without manual declaration.

  • Configured using @ComponentScan (included by default inside @SpringBootApplication).
  • Spring scans the designated base packages and registers any class annotated with stereotype annotations:

    • @Component — Generic Spring-managed component.
    • @Service — Holds business logic.
    • @Repository — Encapsulates database operations and provides exception translation.
    • @Controller / @RestController — Handles HTTP requests in web applications.

4. Java-Based Bean Configuration

Java-based configuration allows you to define and wire beans explicitly using standard Java code rather than legacy XML files or annotations directly on the target class.

  • @Configuration: Marks a class as a source of bean definitions.
  • @Bean: Placed on methods inside a @Configuration class; the object returned by the method is registered as a bean in the Spring container.
  • Useful when configuring third-party library classes that cannot be annotated with @Component, or when custom instantiation logic is required.

5. Multiple Bean Selection

When multiple beans implement the same interface or match the same type, Spring needs explicit instructions to resolve ambiguity during injection (preventing NoUniqueBeanDefinitionException).

  • @Primary: Gives higher preference to a specific bean when multiple candidates exist, serving as the default choice.
  • @Qualifier("beanName"): Used at the injection point (e.g., constructor or field) alongside @Autowired to specify the exact bean name to inject.
  • Conditional Selection: Annotations like @ConditionalOnProperty or @Profile can also select active beans dynamically based on configuration values or active runtime environments.
Scroll to Top