โš™๏ธ Container Layer โ€” IoC, Dependency Injection & Context Cheatsheet

Essence: The Container Layer is the heart of Spring โ€” the Inversion of Control (IoC) engine that creates, wires, manages, and coordinates all beans. It gives your application memory, order, and lifecycle.


๐Ÿงญ 1. The Big Idea: Inversion of Control (IoC)

Traditional Java:

PaymentService service = new PaymentService(new AuditService());

Spring style:

@Autowired
PaymentService service;

The control has been inverted โ€” Spring now decides when and how to create your objects.


๐Ÿ” What IoC Means

  • You declare what classes exist and how they relate.
  • The container builds and connects them at runtime.
  • Your code depends on abstractions, not construction logic.

IoC is the philosophy; Dependency Injection (DI) is the mechanism that makes it happen.


๐Ÿค 2. Dependency Injection โ€” The Wiring Mechanism

Types of Injection

Style Example When to Use
Constructor public Service(Repo r) Preferred โ€” immutable, required deps
Setter @Autowired setRepo(Repo r) Optional dependencies
Field @Autowired Repo repo; Simple, less testable

Injection Flow

1. Container identifies required dependencies.
2. Finds matching beans by type.
3. Injects via reflection (constructor, field, or setter).
4. Calls @PostConstruct or init methods.

๐Ÿงฉ Qualifiers and Primary

When multiple beans match a type:

@Service("emailNotifier")
public class EmailNotifier implements Notifier {}

@Primary
@Service
public class SmsNotifier implements Notifier {}
@Autowired
@Qualifier("emailNotifier")
private Notifier notifier;

Spring rules:

  1. Match by type.
  2. If multiple found โ†’ use @Primary.
  3. If qualified โ†’ use that exact name.
  4. If none โ†’ throw NoSuchBeanDefinitionException.

โš™๏ธ Optional and Lazy Dependencies

@Autowired(required = false)
private Optional<AuditService> audit;

@Autowired
@Lazy
private HeavyService heavy; // created on first use

๐Ÿงฑ Collection Injection

Spring can inject multiple beans of the same type as a list or map:

@Autowired
private List<PaymentProcessor> processors;

@Autowired
private Map<String, PaymentProcessor> processorMap;

๐Ÿงฉ 3. BeanFactory โ€” The Core Container

BeanFactory is the lowest-level IoC interface โ€” minimal and efficient.

Core Responsibilities

  • Hold BeanDefinitions (metadata)
  • Instantiate beans via reflection
  • Perform dependency injection
  • Handle scopes (singleton, prototype, etc.)
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("app.xml"));
MyService s = factory.getBean(MyService.class);

Key Methods

Method Purpose
getBean(String name) Retrieve bean by name
getBean(Class<T> type) Retrieve by type
containsBean(String name) Check existence
isSingleton(String name) Check scope
getType(String name) Get class type

Note: You rarely use BeanFactory directly โ€” itโ€™s the internal engine behind ApplicationContext.


๐Ÿงญ 4. ApplicationContext โ€” The Intelligent Container

ApplicationContext extends BeanFactory and adds:

  • Lifecycle events
  • Resource loading
  • Environment & profiles
  • Internationalization
  • AOP integration
  • Startup hooks (CommandLineRunner, ApplicationRunner)

Typical Usage

ApplicationContext ctx =
        new AnnotationConfigApplicationContext(AppConfig.class);

MyService s = ctx.getBean(MyService.class);
ctx.getBean("auditService", AuditService.class);

Context Implementations

Implementation Purpose
AnnotationConfigApplicationContext Java-based config
ClassPathXmlApplicationContext XML config
FileSystemXmlApplicationContext From filesystem path
WebApplicationContext Web-aware context (Spring MVC)

Lifecycle Sequence

create context
  โ†“
load BeanDefinitions
  โ†“
instantiate beans
  โ†“
inject dependencies
  โ†“
call lifecycle methods
  โ†“
publish ContextRefreshedEvent
  โ†“
app ready
  โ†“
on shutdown โ†’ ContextClosedEvent โ†’ destroy beans

Event Publishing

@Component
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
    public void onApplicationEvent(ContextRefreshedEvent e) {
        System.out.println("Context ready!");
    }
}

or

@EventListener
public void handleShutdown(ContextClosedEvent e) {
    System.out.println("Context closing...");
}

Environment & Profiles

@Profile("dev")
@Bean
public DataSource devDataSource() { ... }

@Profile("prod")
@Bean
public DataSource prodDataSource() { ... }

Active profile:

--spring.profiles.active=dev

โš™๏ธ 5. Bean Post-Processing

Post-processors modify beans before and after initialization.

@Component
public class MetricsInjector implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) {
        // before @PostConstruct
        return bean;
    }
    public Object postProcessAfterInitialization(Object bean, String name) {
        // after initialization
        return bean;
    }
}

Used for:

  • Autowiring processing
  • @Transactional proxies
  • Caching
  • Validation

๐Ÿงฎ 6. Context Hierarchies

Large applications may use multiple contexts:

Parent Context (shared configs)
   โ†“
Child Context (web layer, modules)

A child context can access parent beans but not vice versa. Used in modular systems or Spring MVC applications.


๐Ÿง  7. Common Patterns

Access the Context

@Component
public class ContextAwareBean implements ApplicationContextAware {
    private ApplicationContext ctx;
    public void setApplicationContext(ApplicationContext c) {
        this.ctx = c;
    }
}

Programmatic Bean Access

@Autowired
ApplicationContext ctx;
MyService s = ctx.getBean(MyService.class);

Manual Refresh

AnnotationConfigApplicationContext ctx =
        new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();

๐Ÿงฉ 8. Typical Bean Lifecycle (Container Perspective)

register BeanDefinition
    โ†“
BeanFactory creates instance
    โ†“
Autowired dependencies injected
    โ†“
BeanPostProcessors run
    โ†“
@PostConstruct / afterPropertiesSet()
    โ†“
Context publishes events
    โ†“
Bean used during runtime
    โ†“
@PreDestroy / destroy()

โš™๏ธ 9. Common Pitfalls

Symptom Cause Fix
BeanCurrentlyInCreationException Circular dependencies Use setter or lazy injection
NoSuchBeanDefinitionException Missing bean Check component scan
IllegalStateException: context closed Using context after shutdown Manage lifecycle properly
@Autowired not working Class not scanned Adjust @ComponentScan
Multiple beans found Ambiguous type Use @Qualifier or @Primary

๐Ÿงญ 10. Container Class Hierarchy Summary

BeanFactory
  โ†‘
ListableBeanFactory
  โ†‘
HierarchicalBeanFactory
  โ†‘
ApplicationContext
   โ”œโ”€ AnnotationConfigApplicationContext
   โ”œโ”€ ClassPathXmlApplicationContext
   โ””โ”€ WebApplicationContext

๐Ÿงฑ 11. Quick Reference Summary

Concept API / Annotation Description
Inversion of Control โ€” Framework controls object creation
Dependency Injection @Autowired, @Qualifier Auto-wiring of beans
Core container BeanFactory Low-level bean management
Full container ApplicationContext IoC + events + resources
Bean lookup getBean(Class<T>) Retrieve from context
Lifecycle @PostConstruct, @PreDestroy Init/destroy hooks
Events ApplicationEvent, @EventListener Pub/sub system
Profiles @Profile Conditional bean loading


๐Ÿชž Core Takeaway

The Container Layer is Springโ€™s mind. It knows what beans exist, how they depend on each other, and when they should live or die. Reflection builds them, the Container awakens them โ€” making IoC the intelligence that turns plain code into a coordinated ecosystem.