springboot几种优雅关闭服务的方式
通过kill pid命令可触发的关闭服务资源的几种方式,kill -9 pid 无法触发!
1.JVM自带的shutdownHook
Runtime.getRuntime().addShutdownHook(new Thread(() -> log.info("shutdown!!!")));
比如在启动函数中添加:
@SpringBootApplication
@Slf4j
public class WebApplication {
public static void main(String[] args) {
java.lang.Runtime.getRuntime().addShutdownHook(new Thread(()->{
log.info("程序退出啦!");
}));
SpringApplication.run(WebApplication.class, args);
}
}
2.实现DisposableBean接口
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory;
/**
* Interface to be implemented by beans that want to release resources on destruction.
* A {@link BeanFactory} will invoke the destroy method on individual destruction of a
* scoped bean. An {@link org.springframework.context.ApplicationContext} is supposed
* to dispose all of its singletons on shutdown, driven by the application lifecycle.
*
* <p>A Spring-managed bean may also implement Java's {@link AutoCloseable} interface
* for the same purpose. An alternative to implementing an interface is specifying a
* custom destroy method, for example in an XML bean definition. For a list of all
* bean lifecycle methods, see the {@link BeanFactory BeanFactory javadocs}.
*
* @author Juergen Hoeller
* @since 12.08.2003
* @see InitializingBean
* @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName()
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
//由想要在销毁时释放资源的 Bean 实现的接口。BeanFactory 将在单个销毁作用域内的 Bean 时调用 destroy 方法。一个组织 springframework。上下文。ApplicationContext 应该在关闭时释放其所有单例,由应用程序生命周期驱动。Spring 管理的 bean 也可以出于相同的目的实现 Java 的 AutoCloseable 接口。实现接口的替代方法是指定自定义销毁方法,例如在 XML Bean 定义中。有关所有 Bean 生命周期方法的列表,请参阅 BeanFactory javadocs。
public interface DisposableBean {
/**
* Invoked by the containing {@code BeanFactory} on destruction of a bean.
* @throws Exception in case of shutdown errors. Exceptions will get logged
* but not rethrown to allow other beans to release their resources as well.
*/
//由包含的 BeanFactory 在销毁 Bean 时调用。抛出:异常 – 在发生关机错误的情况下。异常将被记录,但不会被重新抛出,以允许其他 Bean 也释放其资源。
void destroy() throws Exception;
}
3.监听spring的ContextClosedEvent
spring提供了各种监听事件,可以参照以下示例(内容来自Spring官网)
Sr.No | Spring Built-in Events | Description |
---|---|---|
1 | ContextRefreshedEvent | This event is published when the ApplicationContext is either initialized or refreshed. This can also be raised using the refresh() method on the ConfigurableApplicationContext interface. |
2 | ContextStartedEvent | This event is published when the ApplicationContext is started using the start() method on the ConfigurableApplicationContext interface. You can poll your database or you can restart any stopped application after receiving this event. |
3 | ContextStoppedEvent | This event is published when the ApplicationContext is stopped using the stop() method on the ConfigurableApplicationContext interface. You can do required housekeep work after receiving this event. |
4 | ContextClosedEvent | This event is published when the ApplicationContext is closed using the close() method on the ConfigurableApplicationContext interface. A closed context reaches its end of life; it cannot be refreshed or restarted. |
5 | RequestHandledEvent | This is a web-specific event telling all beans that an HTTP request has been serviced. |
实现ApplicationListener接口,监听ContextClosedEvent
@Component
@Slf4j
public class ShutdownListener implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
log.info("shutdown!!! ");
}
}
4.使用注解@PreDestroy
javax.annotation.PreDestroy,
/**
* The PreDestroy annotation is used on methods as a callback notification to
* signal that the instance is in the process of being removed by the
* container. The method annotated with PreDestroy is typically used to
* release resources that it has been holding. This annotation MUST be
* supported by all container managed objects that support PostConstruct
* except the application client container in Java EE 5. The method on which
* the PreDestroy annotation is applied MUST fulfill all of the following
* criteria:
* <p>
* <ul>
* <li>The method MUST NOT have any parameters except in the case of
* interceptors in which case it takes an InvocationContext object as
* defined by the Interceptors specification.</li>
* <li>The method defined on an interceptor class MUST HAVE one of the
* following signatures:
* <p>
* void <METHOD>(InvocationContext)
* <p>
* Object <METHOD>(InvocationContext) throws Exception
* <p>
* <i>Note: A PreDestroy interceptor method must not throw application
* exceptions, but it may be declared to throw checked exceptions including
* the java.lang.Exception if the same interceptor method interposes on
* business or timeout methods in addition to lifecycle events. If a
* PreDestroy interceptor method returns a value, it is ignored by
* the container.</i>
* </li>
* <li>The method defined on a non-interceptor class MUST HAVE the
* following signature:
* <p>
* void <METHOD>()
* </li>
* <li>The method on which PreDestroy is applied MAY be public, protected,
* package private or private.</li>
* <li>The method MUST NOT be static.</li>
* <li>The method MAY be final.</li>
* <li>If the method throws an unchecked exception it is ignored except in the
* case of EJBs where the EJB can handle exceptions.</li>
* </ul>
*
* @see javax.annotation.PostConstruct
* @see javax.annotation.Resource
* @since Common Annotations 1.0
*/
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}
PreDestroy 注释在方法上用作回调通知,以指示实例正在被容器删除。使用 PreDestroy 批注的方法通常用于释放它一直持有的资源。除 Java EE 5 中的应用程序客户机容器外,所有支持 PostConstruct 的容器托管对象都必须支持此注释。
使用如下:
@PreDestroy
public void destroy() {
log.info("Pre destroy shutdown!!! ");
}
对于@PreDestroy会存在一个不生效的情况,对于Scope为prototype的bean,Spring不会调用@PreDestory标记的方法。