๐ŸŒฟ Beans Layer โ€” Anatomy, Annotations & Lifecycle Cheatsheet

Essence: Beans are the living objects Spring creates, wires, and manages inside the ApplicationContext. The Beans Layer covers what they are, how they live and die, and how their metadata is described through BeanDefinitions.


๐Ÿงญ 1. Concept Overview

A Spring bean is a normal Java object, but:

  • Its lifecycle is controlled by the Spring container, not you.
  • Itโ€™s created via reflection, wired via dependency injection, and destroyed gracefully.
  • Everything about it โ€” class, scope, dependencies, and init/destroy callbacks โ€” is stored in a BeanDefinition.

Think of each bean as a citizen of Springโ€™s managed world โ€” born, connected, and retired by the container.


๐Ÿงฉ 2. Declaring Beans

You can register beans in three main ways:

๐Ÿงฑ Component Scanning (Annotation-based)

@Component
public class PaymentService {}

Spring scans packages for these stereotypes:

Annotation Role
@Component Generic Spring-managed bean
@Service Service-layer bean (semantic marker)
@Repository Persistence-layer bean (adds exception translation)
@Controller Web MVC component
@Configuration Source of explicit bean definitions

โš™๏ธ Explicit Bean Registration (Configuration Class)

@Configuration
public class AppConfig {
    @Bean
    public AuditService auditService() {
        return new AuditService();
    }
}

Each @Bean method returns an object that Spring registers as a managed bean.


๐Ÿงฎ XML Configuration (Legacy)

<bean id="paymentService" class="com.app.PaymentService"/>

Old style, still supported but rarely used in modern applications.


๐Ÿงฌ 3. BeanDefinition โ€” The Blueprint Metadata

When Spring detects a bean, it doesnโ€™t create it immediately. It first builds a BeanDefinition โ€” a metadata record describing:

Property Meaning
beanClass Actual Class<?>
scope singleton, prototype, etc.
autowireMode How dependencies are injected
initMethodName Custom initialization method
destroyMethodName Cleanup method
lazyInit Whether bean is created on demand
dependsOn Other beans that must be created first

Example (simplified pseudocode):

BeanDefinition bd = new BeanDefinition();
bd.setBeanClass(PaymentService.class);
bd.setScope("singleton");
bd.setInitMethodName("init");
bd.setDestroyMethodName("cleanup");

This blueprint is what the BeanFactory later uses to actually create the instance.


โš™๏ธ 4. Bean Scopes โ€” Controlling Lifespan

Scope Meaning Created Destroyed
singleton One instance per container On context start On context close
prototype New instance per request On demand Not tracked
request One per HTTP request On web request start On web request end
session One per HTTP session On session start On session end
application One per ServletContext On context init On shutdown
@Component
@Scope("prototype")
public class Task {}

๐Ÿง  5. Bean Lifecycle Stages

1. Definition created (BeanDefinition)
2. Instance constructed (reflection)
3. Dependencies injected (@Autowired, @Value)
4. Lifecycle callbacks triggered (@PostConstruct, init-method)
5. Bean enters ready state
6. On context shutdown โ†’ @PreDestroy or destroy-method called

Lifecycle Annotations and Interfaces

Type Example Purpose
Annotation @PostConstruct After injection
Annotation @PreDestroy Before destruction
Interface InitializingBean.afterPropertiesSet() Post-injection initialization
Interface DisposableBean.destroy() Cleanup
XML Attr init-method / destroy-method Legacy equivalent

Example

@Component
public class ConnectionPool {

    @PostConstruct
    public void init() { System.out.println("Pool ready"); }

    @PreDestroy
    public void shutdown() { System.out.println("Pool closed"); }
}

Output:

Pool ready
...
Pool closed

๐Ÿงฉ 6. Dependency Injection Timing

Spring always injects dependencies before calling any init methods. Thatโ€™s why you can safely rely on @Autowired fields or constructor-injected dependencies inside your @PostConstruct.

instantiate โ†’ inject โ†’ initialize โ†’ active โ†’ destroy

๐Ÿงฎ 7. Lazy and Conditional Beans

Lazy

@Component
@Lazy
public class ExpensiveBean {}

Created only when first requested.

Conditional

@Bean
@ConditionalOnProperty("feature.x.enabled")
public FeatureX feature() { return new FeatureX(); }

Used heavily in Spring Boot auto-configuration.


๐Ÿงญ 8. Common Pitfalls

Symptom Cause Fix
BeanCurrentlyInCreationException Circular dependency Break cycle or use @Lazy
NullPointerException on injected field Bean not scanned Fix @ComponentScan path
NoSuchBeanDefinitionException No bean found Annotate or register bean
Init/destroy not called Wrong signature Must be public void no-arg method
Prototype beans not destroyed Expected behavior Manage manually if needed

โš™๏ธ 9. Inspecting Beans at Runtime

@Autowired
ApplicationContext ctx;

public void debugBeans() {
    for (String name : ctx.getBeanDefinitionNames()) {
        System.out.println(name + " โ†’ " + ctx.getType(name));
    }
}

๐Ÿงฉ 10. Custom BeanPostProcessor

Advanced hook that modifies beans before/after initialization.

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

Used internally for:

  • Autowiring processor
  • AOP proxy creation
  • Validation, caching, and more

๐Ÿงญ 11. Quick Reference Summary

Concept API / Annotation Purpose
Declare bean @Component, @Service, @Bean Register with container
Describe bean BeanDefinition Internal metadata
Define scope @Scope("...") Control lifespan
Init phase @PostConstruct / afterPropertiesSet() Setup
Destroy phase @PreDestroy / destroy() Cleanup
Post-processing BeanPostProcessor Modify beans
Lazy loading @Lazy Create on demand
Conditional creation @Conditional... Context-based activation

@Component โ†’ Scanned by Reflection
     โ†“
BeanDefinition โ†’ Metadata stored
     โ†“
BeanFactory โ†’ Instantiates using reflection
     โ†“
@Autowire / @Value โ†’ Dependencies injected
     โ†“
@PostConstruct โ†’ Init logic
     โ†“
Context Active
     โ†“
@PreDestroy โ†’ Cleanup

BeanDefinition is the blueprint; the Bean instance is the living object built from it.



๐Ÿชž Core Takeaway

Reflection lets Spring build objects. The Beans Layer teaches them how to live. Every bean in the container is born from a BeanDefinition, configured through annotations, and guided through a full lifecycle โ€” from reflective creation to graceful destruction.