Spring Lifecycle Methods

📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.

✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.

🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.

▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube

 When a Spring application starts, it goes through a series of steps to create, configure, and manage the lifecycle of its beans. Understanding this lifecycle is critical for building robust, maintainable, and resource-efficient Spring applications.

In this article, we’ll walk through the Spring bean lifecycle, explain the key lifecycle methods, and demonstrate each with clear examples and best practices.

What Is the Spring Bean Lifecycle?

A Spring bean goes through multiple phases from the moment it’s instantiated to the point it’s destroyed. These phases include:

  1. Instantiation
  2. Property Injection
  3. Initialization
  4. Use (Application logic)
  5. Destruction

Spring provides various hooks and interfaces that allow you to run custom logic at different points in this lifecycle.

🧬 Common Lifecycle Methods in Spring

Let’s look at each one in detail.

1. Using @PostConstruct for Initialization

This annotation is used on a method that should run after the bean is constructed and dependencies are injected.

Example:

@Component
public class EmailService {

@PostConstruct
public void init() {
System.out.println("EmailService initialized");
}
}

Best Practice:

Use @PostConstruct for lightweight, dependency-based initialization logic like setting defaults, logging, or preloading data.

2. Implementing InitializingBean

If you want more control or avoid annotations, implement InitializingBean.

Example:

@Component
public class PaymentService implements InitializingBean {

@Override
public void afterPropertiesSet() {
System.out.println("PaymentService has been initialized via InitializingBean");
}
}

Best Practice:

Use InitializingBean when working with frameworks or libraries that require interface-based initialization logic.

3. Using Custom initMethod in @Bean

You can define an initialization method explicitly in a configuration class.

Example:

@Configuration
public class AppConfig {

@Bean(initMethod = "init")
public NotificationService notificationService() {
return new NotificationService();
}
}
public class NotificationService {
public void init() {
System.out.println("NotificationService custom init method called");
}
}

Best Practice:

Good for third-party classes where you can’t annotate or implement interfaces.

🧹 4. Using @PreDestroy for Cleanup

This hook runs just before the Spring container destroys the bean.

Example:

@Component
public class CacheManager {

@PreDestroy
public void cleanUp() {
System.out.println("CacheManager cleaned up before shutdown");
}
}

Best Practice:

Use @PreDestroy for releasing resources like file handles, threads, or connections.

5. Implementing DisposableBean for Cleanup

Like InitializingBean, you can use this interface for bean destruction logic.

Example:

@Component
public class FileWriterService implements DisposableBean {

@Override
public void destroy() {
System.out.println("FileWriterService resources released");
}
}

Best Practice:

Use when annotation-free or interface-based design is preferred.

6. Using Custom destroyMethod in @Bean

Configure a destroy method in a @Bean definition.

Example:

@Configuration
public class ShutdownConfig {

@Bean(destroyMethod = "shutdown")
public TaskProcessor taskProcessor() {
return new TaskProcessor();
}
}
public class TaskProcessor {
public void shutdown() {
System.out.println("TaskProcessor shutting down cleanly...");
}
}

Best Practice:

Useful for external libraries where annotations and interfaces can’t be added.

🧭 Lifecycle Flow Recap (Execution Order)

  1. Constructor called
  2. Dependencies injected
  3. @PostConstruct method called
  4. afterPropertiesSet() (if implemented)
  5. Custom initMethod (if defined)
  6. Application runs…
  7. @PreDestroy called on shutdown
  8. destroy() method (if implemented)
  9. Custom destroyMethod (if defined)

🧠 Real-World Use Cases

Best Practices for Bean Lifecycle Management

  • Prefer @PostConstruct and @PreDestroy for modern Spring apps.
  • Use @Bean(initMethod = "...", destroyMethod = "...") for external classes.
  • Avoid using multiple lifecycle mechanisms in the same class.
  • Don’t perform heavy operations (like API calls or blocking IO) directly in lifecycle methods — consider background tasks.

✅ Conclusion

Spring provides multiple ways to hook into the bean lifecycle, giving you flexibility for both initialization and cleanup. Choose the right one based on your use case:

  • Annotations (@PostConstruct, @PreDestroy) → Clean and easy for modern apps.
  • Interfaces (InitializingBean, DisposableBean) → Useful for frameworks or legacy code.
  • @Bean methods with initMethod/destroyMethod → Great for third-party classes.
Understanding lifecycle methods helps you write robust, maintainable, and resource-efficient Spring applications.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare