【问题标题】:Best way for a Grails Service class to detect application shutdown?Grails 服务类检测应用程序关闭的最佳方法?
【发布时间】:2011-07-30 08:20:33
【问题描述】:

我有一个 Grails 服务类,当我的 Tomcat 应用程序服务器关闭时需要进行一些清理。

我在 Grails 文档中没有看到任何关于 service.stop() 或 destroy() 方法,或者实现任何类型的应用程序生命周期侦听器的方法。

最好的方法是什么?

谢谢!

【问题讨论】:

    标签: grails groovy service application-lifecycle


    【解决方案1】:

    这与服务处置方法不太一样,但我最终做的是注册一个 Spring Bean,并在应用停止时调用该方法。

    首先,创建一个 bean 类,如 grails-app/utils/MyShutdownBean.groovy,如下所示(类名或方法名没有什么神圣的,随便你用):

    class MyShutdownBean {
        public void cleanup() {
            // Do cleanup stuff
        }
    }
    

    然后像这样在grails-app/conf/spring/resources.groovy注册bean:

    beans = {
        myShutdownHook(MyShutdownBean) { bean ->
            bean.destroyMethod='cleanup'
        }
    }
    

    如果您只想在生产环境中进行清理,则可以这样注册:

    beans = {
        if (!grails.util.GrailsUtil.isDevelopmentEnv()) {
            myShutdownHook(MyShutdownBean) { bean ->
                bean.destroyMethod='cleanup'
            }
        }
    }
    

    【讨论】:

    • 如何确保它在 Tomcat 死机时运行?如果 bean 从未实例化怎么办?如果它被垃圾收集怎么办?它不会在你想要它之前运行你的清理吗?
    【解决方案2】:

    grails-app/conf/BootStrap.groovy 可以在应用启动和停止时使用。

    def init = {
      println 'Hello World!'
    }
    
    def destroy = {
      println 'Goodnight World!'
    }
    

    注意:当在某些操作系统的CTL+C 上使用开发模式grails run-app 时,会在没有机会彻底关闭的情况下杀死JVM,并且可能不会调用destroy 闭包。此外,如果您的 JVM 获得 kill -9,则闭包也不会运行。

    【讨论】:

    • 这个答案不适合这个问题,问题特别要求在应用程序关闭的情况下通知服务。虽然如果只要求在应用程序关闭时做一些事情,那么它就足够了。如果想将服务 bean 注入 Bootstrap,@Maricel 的答案更接近答案。
    【解决方案3】:

    你有几个选择

    让你的服务实现org.springframework.beans.factory.DisposableBean

    class MyService implements org.springframework.beans.factory.DisposableBean {
    
        void destroy() throws Exception {
    
        }
    }
    

    或者使用注释

    class MyService {
    
        @PreDestroy
        private void cleanUp() throws Exception {
    
        }
     }
    

    IMO,注释选项更可取,因为您可以为析构函数指定一个比 destroy 更有意义的名称,并且您的类公共 API 不会暴露 Spring 依赖项

    【讨论】:

    • 谢谢,太好了!同意我更喜欢@PreDestroy,以免暴露 Spring 依赖项,而且发生的事情更清楚。
    【解决方案4】:

    我会尝试将服务注入 Bootstrap,然后从销毁块调用该方法,因为销毁块是在应用程序终止时执行的,如下所示:

    class BootStrap {
    
        def myService
    
        def init = {servletContext ->
        }
    
        def destroy = {
           myService.cleanUp()
        }
    }
    

    【讨论】:

    • 很高兴知道,马里塞尔。虽然在这种情况下,我喜欢能够按照 Don 的建议使用 @PreDestroy,因为它非常干净且简单地将清理与需要清理的服务联系起来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多