java hook function (hook) take spring source code as an example

1, What is a hook function

In Spring, if the JVM terminates abnormally, how does Spring ensure that the occupied resources, such as database connections, will be released? The hook function is so simple that you can just extract a piece of Spring code.

2, Question

When does the Bean in the Spring container execute the destruction method? We know that there are two ways to define destruction methods in Spring to implement the destroy method of DisposableBean. Decorate the method with @ PreDestroy annotation

@Component
public class DataCollectBean implements DisposableBean {
    /**
     * The first method implements the DisposableBean#destroy method
     *
     * @throws Exception abnormal
     */
    @Override
    public void destroy() throws Exception {
        System.err.println("Execute destruction method");
    }
    /**
     * The second method uses the PreDestroy annotation to declare the destruction method
     */
    @PreDestroy
    public void customerDestroy() {
        System.err.println("Execute custom destroy method");
    }
}

3, So when will the destruction method be executed?

  1. Actively destroy bean s
public static void main(String[] args) {
    ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
    DataCollectBean bean = run.getBean(DataCollectBean.class);
    //1. Actively destroy bean s
    run.getBeanFactory().destroyBean(bean);
}
  1. The destruction method is automatically executed when the JVM is shut down.
    Here we need to use the hook function. The Spring hook function is in the AbstractApplicationContext#shutdownHook attribute. If we are a Spring boot project, we see that a hook function will be registered when the Spring application is started

4, How to define hook functions?

It's too simple. There's no learning cost. One line of code.

public class HooksTester {
    public static void main(String[] args) {
    //Define hook function
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Hook function execution");
            }
        }));
        //When actively closing the application
        while (true);
    }
}

5, Scenario of triggering hook function

As long as the machine is not powered off, the forced kill -9 process will be triggered.

6, What can hook functions do?

As shown in the figure above, when the project is about to be shut down, actively release the resource information occupied by the program and other occupied resource information such as the connection of db connection pool. If we are a Spring project, we don't need to define our own hook function. We just need to use the destruction method provided by Spring. Because the hook function defined by Spring will execute disposablebean Destroy() and PreDestroy modified methods.

  • Source code
protected void doClose() {
        // Check whether an actual close attempt is necessary...
        if (this.active.get() && this.closed.compareAndSet(false, true)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Closing " + this);
            }
            LiveBeansView.unregisterApplicationContext(this);
            try {
                // Publish shutdown event.
                publishEvent(new ContextClosedEvent(this));
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
            }
            // Stop all Lifecycle beans, to avoid delays during individual destruction.
            if (this.lifecycleProcessor != null) {
                try {
                    this.lifecycleProcessor.onClose();
                }
                catch (Throwable ex) {
                    logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
                }
            }
            // Destroy all cached singletons in the context's BeanFactory.
            destroyBeans();
            // Close the state of this context itself.
            closeBeanFactory();
            // Let subclasses do some final clean-up if they wish...
            onClose();
            // Reset local application listeners to pre-refresh state.
            if (this.earlyApplicationListeners != null) {
                this.applicationListeners.clear();
                this.applicationListeners.addAll(this.earlyApplicationListeners);
            }
            // Switch to inactive.
            this.active.set(false);
        }
    }

It can be seen that the doClose() method will execute the destroy() method of the bean and the stop() method of the SmartLifeCycle. We can rewrite these methods to realize object closing, life cycle management and smooth shutdown

Article transferred from

Keywords: Java Spring

Added by darrensw on Thu, 23 Dec 2021 05:30:09 +0200