Q: What are Bean Scopes and the Bean Lifecycle in Spring?

Answer:

Bean Scopes

A bean's scope defines how many instances Spring creates and how long they live.

ScopeInstancesLifecycleUse Case
singleton (default)1 per ApplicationContextApp startup → shutdownStateless services, repositories
prototypeNew instance per injection/requestCreated on demand, NOT destroyed by SpringStateful objects, builders
request1 per HTTP requestRequest start → endRequest-scoped data
session1 per HTTP sessionSession start → invalidationUser session data
application1 per ServletContextApp startup → shutdownGlobal web-app state
@Component
@Scope("prototype")
public class ShoppingCart { /* new instance per injection */ }

Bean Lifecycle

                  Bean Lifecycle
                  
1. Instantiation    → Constructor called
2. Populate Props   → Dependencies injected (@Autowired)
3. BeanNameAware    → setBeanName() if interface implemented
4. BeanFactoryAware → setBeanFactory()
5. Pre-Init         → @PostConstruct / BeanPostProcessor.postProcessBeforeInitialization()
6. Init             → InitializingBean.afterPropertiesSet() / custom init-method
7. Post-Init        → BeanPostProcessor.postProcessAfterInitialization()
8. ═══ Bean is READY to use ═══
9. Pre-Destroy      → @PreDestroy
10. Destroy         → DisposableBean.destroy() / custom destroy-method

Practical Example

@Component
public class DatabaseConnectionPool {
    
    private HikariDataSource dataSource;
    
    @Autowired
    public DatabaseConnectionPool(DataSourceProperties props) {
        // Step 1-2: Constructor + injection
    }
    
    @PostConstruct  // Step 5: Called after all dependencies are injected
    public void init() {
        this.dataSource = createPool();
        log.info("Connection pool initialized with {} connections", poolSize);
    }
    
    @PreDestroy  // Step 9: Called before bean is destroyed (app shutdown)
    public void cleanup() {
        dataSource.close();
        log.info("Connection pool closed gracefully");
    }
}

Singleton Gotcha with Prototype

@Component // Singleton by default
public class OrderService {
    @Autowired
    private ShoppingCart cart; // Prototype-scoped
    // ❌ PROBLEM: Same cart instance is used for ALL requests!
    // The prototype bean is injected ONCE into the singleton.
}

// ✅ Fix: Use ObjectProvider or @Lookup
@Component
public class OrderService {
    @Autowired
    private ObjectProvider<ShoppingCart> cartProvider;
    
    public void process() {
        ShoppingCart cart = cartProvider.getObject(); // New instance each time
    }
}

[!CAUTION] Injecting a prototype-scoped bean into a singleton is a common mistake. The prototype is created once during singleton initialization and reused forever. Use ObjectProvider, @Lookup, or ObjectFactory to get a new prototype instance each time.