@PostConstruct and @PreDestroy in the Bean Lifecycle
`@PostConstruct` marks a method to run after a bean has been constructed and its dependency injection is complete. `@PreDestroy` marks a method for cleanup before the container destroys the bean.
These annotations are commonly used with dependency-injection containers such as Spring. A bean is first instantiated, then its dependencies and other container-managed properties are populated; a `@PostConstruct` method runs after that initialization phase, making it suitable for setup that requires injected dependencies.
A `@PreDestroy` method runs when the container is destroying a managed bean. It is intended for cleanup such as releasing resources that the bean itself acquired during its lifetime.
The methods are lifecycle callbacks, not ordinary application methods that you call as part of business logic. The container discovers the annotations and invokes the callbacks at the appropriate lifecycle stage. For modern Java applications, the annotation is provided by `jakarta.annotation.PostConstruct` and `jakarta.annotation.PreDestroy`; older applications may use the corresponding `javax.annotation` package.
A lifecycle callback generally should be small and focused. Avoid putting essential business operations there, and remember that destruction callbacks depend on the object actually being managed by the container and on the container performing its normal destruction lifecycle.
Key points
- `@PostConstruct` runs after dependency injection and initialization of a managed bean.
- `@PreDestroy` runs during destruction of a managed bean.
- The container invokes these methods; application code normally does not call them directly.
- Use initialization callbacks for setup that needs injected dependencies and destruction callbacks for resource cleanup.
- The annotation package is `jakarta.annotation` in modern Jakarta-based applications; older code may use `javax.annotation`.
Interview questions
What package should modern Jakarta-based Java applications import for these annotations?
Modern Jakarta-based applications use `jakarta.annotation.PostConstruct` and `jakarta.annotation.PreDestroy`. Older Java applications may contain the same annotations under `javax.annotation`. The correct import therefore depends on the API generation and dependencies used by the project. When maintaining existing code, the project's framework and dependency versions should determine which namespace is appropriate.
What is the purpose of `@PostConstruct`?
`@PostConstruct` identifies a lifecycle callback that the dependency-injection container invokes after the bean has been constructed and its dependencies have been injected. It is useful when initialization needs those injected dependencies. For example, a service could initialize an internal cache using an injected repository. It is generally better suited to this work than putting it in the constructor.
When is `@PreDestroy` used?
`@PreDestroy` marks a method that the container calls when it is destroying a managed bean. It is intended for cleanup of resources owned by that bean, such as shutting down a component or closing a resource. The callback is part of the container's destruction lifecycle. It should not be treated as a universal guarantee that it will execute for every possible JVM termination scenario.
Why might you prefer `@PostConstruct` over initialization in the constructor?
A constructor executes as the Java object is being created, before dependency injection has populated container-managed dependencies. A `@PostConstruct` callback occurs after that injection phase, so initialization can safely use those dependencies. This separates object construction from container-dependent initialization. The constructor is still appropriate for invariants that must hold immediately after Java construction.
What happens if a class is created with `new` instead of being managed by Spring or another container?
The lifecycle annotations do not themselves make an object container-managed. If application code creates the object directly with `new`, the container does not get an opportunity to invoke its lifecycle callbacks. Consequently, `@PostConstruct` and `@PreDestroy` should not be expected to run automatically. The exact lifecycle behavior depends on the framework and how the object is registered and managed.