Java Omnibus
OOAD & Architecture / Dependency Injection / IoC / IoC Containers and Spring in Java
Dependency Injection IoC Java Order Management
Dependency Injection / IoC

IoC containers matter because once a system has many objects, somebody must own creation, lifecycle, and wiring consistently.

Dependency Injection can be done manually, but as a Java system grows, object creation, scopes, configuration, and cross-cutting wiring become harder to manage by hand. IoC containers solve that operational problem. Spring became the dominant Java mental model because it turned DI into a practical, large-scale development style.

Why This Topic Matters

Why it matters in real Java systems

Order Management systems accumulate repositories, gateways, policies, message publishers, schedulers, and controllers. An IoC container centralizes how those parts are assembled so the application code can focus on business behavior instead of manual composition logic.

Core Explanation

The main design idea

An IoC container is not just a factory. It is a runtime composition system. It decides how objects are created, which implementation satisfies which dependency, when instances are reused, and how lifecycle hooks are managed. That is why container choice influences architecture, even when the domain model itself remains framework-agnostic.

Spring matters because it normalized constructor injection, component scanning, configuration classes, scopes, profiles, and integration wiring across the Java ecosystem. But the real architectural lesson is bigger than Spring: containers exist to support clean composition, not to justify hidden dependencies or container-aware domain objects.

Concept Breakdown

Key ideas to hold onto

Concept

Container role

The container creates objects, resolves dependencies, and manages lifecycle and scopes.

Concept

Spring’s value

Spring made DI operationally convenient and connected it to configuration, web layers, transactions, and data access.

Concept

Architectural caution

The container should support a good design, not become the design itself.

Java Example

Java example in the Order Management domain

Java example: a small Spring-style configuration
package org.javaomnibus.ecommerce.di;

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

@Configuration
public class CommerceConfiguration {
    @Bean
    public PaymentGateway paymentGateway() {
        return new StripePaymentGateway();
    }

    @Bean
    public PlaceOrderService placeOrderService(
        InventoryService inventoryService,
        PaymentGateway paymentGateway,
        NotificationService notificationService
    ) {
        return new PlaceOrderService(inventoryService, paymentGateway, notificationService);
    }
}
Code Walkthrough

Step by step

  1. The configuration defines how the runtime should assemble application objects.
  2. Dependencies are resolved by the container rather than manually constructed inside business classes.
  3. This makes application composition explicit at the configuration boundary.
  4. The container supports the design, but the service itself still benefits from plain constructor injection.
Real-World Usage

Where this helps in practice

  • Spring Boot service composition
  • Managing environment-specific implementations and profiles
  • Keeping framework wiring separate from domain logic
What Spring Should And Should Not Own

What Spring Should And Should Not Own

Good fit

Container-owned concerns

Configuration, wiring, profiles, transactions, web adapters, messaging adapters, and integration assembly are all natural container concerns.

Be careful

Design-owned concerns

Domain modeling, boundaries, policies, use cases, and aggregate behavior should stay understandable even outside the container.

Trade-Offs

When to be careful

Containers simplify large-scale wiring, but they can also hide architecture if teams overuse framework magic instead of preserving explicit boundaries and readable composition rules.

Common Mistakes

Frequent mistakes to watch for

  • Treating the container as a place to hide poor dependency design
  • Letting framework annotations leak deeply into domain models
  • Using container tricks to paper over circular dependencies
  • Assuming Spring-specific patterns are the same thing as good OO design
Related Pages

Related concepts


What To Read Next