HuntExams Academy logo
JavaAdvanced#spring

Explain Spring Bean lifecycle.

Answer

Instantiate → populate properties → BeanNameAware/BeanFactoryAware → postProcessBeforeInitialization → @PostConstruct / afterPropertiesSet / custom init → postProcessAfterInitialization → use → @PreDestroy / destroy.

Example

@Component
class MyBean {
  @PostConstruct void init() { System.out.println("initialized"); }
  @PreDestroy void cleanup() { System.out.println("destroyed"); }
}

Detailed explanation

The Spring bean lifecycle describes how the Spring container creates, configures, initializes, exposes, and eventually destroys a managed object. It matters because dependency injection alone does not guarantee that a bean is ready to perform application work: some resources need initialization after injection and cleanup during shutdown. Interviewers expect you to explain the sequence, distinguish lifecycle callbacks from BeanPostProcessors, and identify limitations involving scopes and proxies.

For a typical bean, Spring first instantiates the object using a constructor or factory method. Constructor dependencies are resolved during this step; setter and field dependencies are populated afterward. Spring then invokes relevant Aware callbacks, such as setBeanName() from BeanNameAware and setBeanFactory() from BeanFactoryAware. Other callbacks, including ApplicationContextAware, are supported through container infrastructure. These interfaces let a bean access container metadata or services, but ordinary business classes should generally prefer dependency injection over depending directly on the container.

Next comes initialization processing. BeanPostProcessors receive postProcessBeforeInitialization(), and annotation processing invokes @PostConstruct during this phase. Therefore, @PostConstruct is not a separate stage that necessarily follows every before-initialization processor. When distinct initialization methods are configured together, their order is @PostConstruct, InitializingBean.afterPropertiesSet(), then a custom init method, such as one declared through @Bean(initMethod = "init"). Spring subsequently invokes postProcessAfterInitialization(). A processor may return a wrapper or proxy instead of the original bean, which is how many Spring features, including common AOP arrangements, integrate with bean creation. The exposed bean is then available for normal application use.

When the application context closes, Spring invokes registered destruction callbacks for managed singletons: @PreDestroy, DisposableBean.destroy(), and then a configured custom destroy method, when these are distinct methods. Prototype beans are initialized by Spring, but their destruction callbacks are not automatically invoked; cleanup belongs to the caller. Other scopes use their own lifecycle boundaries. In the example, init() runs during initialization and cleanup() runs during managed destruction. For Spring Framework 6 and Spring Boot 3, these annotations come from jakarta.annotation. Callbacks should handle local setup and resource release rather than assume every other bean is fully initialized.

Key points to remember

  • Typical sequence: instantiate → inject dependencies → Aware callbacks → initialization processing → post-initialization processing → use → destruction.
  • @PostConstruct is invoked by a BeanPostProcessor during the before-initialization phase.
  • Distinct initialization callbacks run in this order: @PostConstruct → afterPropertiesSet() → custom init method.
  • BeanPostProcessors can modify or replace beans; post-initialization processing commonly exposes AOP proxies.
  • Managed destruction runs @PreDestroy → destroy() → custom destroy method; prototype cleanup is not automatic.

Common mistakes candidates make

  • Using field-injected dependencies inside the constructor, before Spring has populated them.
  • Treating @PostConstruct as running after every postProcessBeforeInitialization() callback or assuming normal proxy advice already applies there.
  • Assuming destruction callbacks run for prototype beans or are guaranteed during an abrupt process termination.

Likely follow-up questions

How is a BeanPostProcessor different from a BeanFactoryPostProcessor?

A BeanFactoryPostProcessor operates on bean definitions before regular beans are instantiated, allowing configuration metadata to be changed. A BeanPostProcessor operates on bean instances around initialization and can return a replacement object.

Should I prefer @PostConstruct or InitializingBean?

@PostConstruct usually avoids coupling the class to Spring-specific lifecycle interfaces. For a third-party class you cannot modify, configure an existing method using @Bean(initMethod = "...") or XML.

Will @Transactional work on a @PostConstruct method?

In the usual proxy-based transaction setup, you should not rely on it because initialization occurs before the bean's transactional proxy is exposed. Move the transactional work to a separate initialized bean and invoke it through that bean's proxy at an appropriate application lifecycle stage.

Interview tip: State the lifecycle sequence first, then highlight the @PostConstruct processing detail, proxy creation, and prototype cleanup exception.

Related Interview Questions

1
JavaIntermediate#spring

What is the difference between Spring Boot and Spring Framework?

Open
2
JavaIntermediate#jpa

What is JPA vs Hibernate?

Open
3
JavaIntermediate#fundamentals

What is the difference between == and .equals() for Integer in Java?

Open