Лучший способ для класса обслуживания Grails обнаружить завершение работы приложения?

#grails #groovy #service #application-lifecycle

#grails #groovy #Обслуживание #жизненный цикл приложения

Вопрос:

У меня есть класс обслуживания Grails, которому необходимо выполнить некоторую очистку при завершении работы моего сервера приложений Tomcat.

Я ничего не вижу в документах Grails о методе service.stop() или destroy() или способе реализации какого-либо прослушивателя жизненного цикла приложения.

Каков наилучший способ сделать это?

Спасибо!

Ответ №1:

У вас есть пара вариантов

Внедрите свой сервис 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

Комментарии:

1. Спасибо, это здорово! Согласитесь, что я предпочитаю @PreDestroy, чтобы не раскрывать зависимость Spring, и это просто намного понятнее, что происходит.

Ответ №2:

grails-app/conf/BootStrap.groovy может использоваться при запуске и остановке приложения.

 def init = {
  println 'Hello World!'
}

def destroy = {
  println 'Goodnight World!'
}
  

Примечание: При использовании режима разработки grails run-app в некоторых ОС CTL C JVM завершается без возможности чистого завершения работы, и закрытие destroy может не вызываться. Кроме того, если ваша JVM получит kill -9 , закрытие также не будет запущено.

Комментарии:

1. Этот ответ не подходит для вопроса, в вопросе конкретно запрашивается уведомление службы в случае завершения работы приложения. Хотя, если единственным требованием является что-то сделать при завершении работы приложения, то этого достаточно. Ответ @Maricel намного ближе к ответу, если кто-то хочет внедрить компонент service в Bootstrap.

Ответ №3:

Я бы попробовал внедрить службу в Bootstrap, а затем вызвать метод из блока destroy, поскольку блок destroy выполняется при завершении работы приложения, что-то вроде этого:

 class BootStrap {

    def myService

    def init = {servletContext ->
    }

    def destroy = {
       myService.cleanUp()
    }
}
  

Комментарии:

1. Приятно это знать, Марисель. Хотя в этом случае мне нравится возможность использовать @PreDestroy, как предлагает Дон, потому что это так чисто и просто привязывает очистку к сервису, который нуждается в очистке.

Ответ №4:

Это не совсем то же самое, что метод удаления службы, но в итоге я зарегистрировал компонент Spring Bean с помощью метода завершения работы, который вызывается при остановке приложения.

Сначала создайте класс bean, например grails-app/utils/MyShutdownBean.groovy , который выглядит следующим образом (в имени класса или имени метода нет ничего священного, используйте все, что хотите):

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

Затем зарегистрируйте компонент в grails-app/conf/spring/resources.groovy следующим образом:

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

Если вы хотите выполнять очистку только в рабочей среде, вы можете зарегистрировать ее следующим образом:

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

Комментарии:

1. Как это гарантирует, что оно запустится, когда Tomcat умрет? Что, если экземпляр компонента никогда не создавался? Что, если это был собранный мусор? Не будет ли тогда выполняться очистка до того, как вы этого захотите?