I have a Spring bean defined in beans.xml
as follows:
<context:annotation-config />
[...]
<bean id="myBackend" class="mycompany.BackendBean" scope="singleton" />
Inside the bean are 2 methods, which must be executed at the start and before termination of the web application:
public class BackendBean implements IBackend {
private static final Logger LOGGER = LoggerFactory
.getLogger(BackendBean.class);
@PostConstruct
public void init()
{
LOGGER.debug("init");
}
@PreDestroy
public void destroy()
{
LOGGER.debug("destroy");
}
}
When I run the server (mvn jetty:run
), I can see the output of the init
method in the console, from which I conclude that the init
method is executed.
When I press Ctrl-C
and Jetty starts to shut down, I don't see the output of the destroy
method.
What should I change in order for the destroy
method to be executed, when the application is terminated?
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization. This method MUST be invoked before the class is put into service. This annotation MUST be supported on all classes that support dependency injection.
To define setup and teardown for a bean, we simply declare the <bean> with initmethod and/or destroy-method parameters. The init-method attribute specifies a method that is to be called on the bean immediately upon instantiation.
When we annotate a method in Spring Bean with @PostConstruct annotation, it gets executed after the spring bean is initialized. We can have only one method annotated with @PostConstruct annotation. This annotation is part of Common Annotations API and it's part of JDK module javax.
Singleton beans are created when the Spring container is created and are destroyed when the container is destroyed. Singleton beans are shared; only one instance of a singleton bean is created per Spring container. Singleton scope is the default scope for a Spring bean.
For Spring to call @PreDestroy
callback method when you application shuts down, you have to add a shutdown hook and close the application context it in. You could attach the hook to JVM using Runtime.getRuntime().addShutdownHook(Thread)
or to Jetty if it provides such an API. Here is how you'd do it with JVM shutdown hook:
final ApplicationContext appContext = ... // create your application context
// using one of the various application context classes
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
appContext.close();
}});
Here is a subtle point you need to be aware of with "prototype" scoped beans.
For "prototype" scoped beans, Spring does not call the @PreDestroy method.
Here is the answer from the Spring official reference manual :
Section 1.5.2 (see here)
In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean**: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance.
Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding.
To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up.
NOTE: This also applies to XML configuration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With