這個問題已被問過幾次,但我沒有找到準確描述我的情況的帖子。我有一個基于 JavaFX/Spring 引導的應用程序,需要在關閉之前執行一些清理任務。我可以像這樣攔截按下 X 按鈕的事件:primaryStage.setOnCloseRequest(event -> { shutdown(event);}); private void shutdown(WindowEvent event) { if (event != null) { event.consume(); } try { shutdownProcessHub(); Platform.exit(); } catch (Exception ex) { logEntryService.logError(LogEntrySource.SERVICE, LogEntryType.CORE, "Error stopping process hub : " + ex.getMessage(), logger); } }我有一個關機按鈕,它調用相同的方法但參數為空。這兩種關閉我的應用程序的方法都會導致調用 shutdownProcessHub() 方法,該方法可以優雅地停止一堆線程并執行對數據庫的寫入。問題是這個應用程序也可以在沒有 GUI 的情況下運行。在這種部署模式下,我使用 NSSM 創建一個指向啟動應用程序的批處理文件的 Windows 服務。停止上述服務會導致對應用程序進行 CTRL-C 調用,從而完全繞過我的關閉方法。我使用以下代碼注冊了一個關閉鉤子:Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(null)));上述關閉掛鉤在任何形式的 Spring bean 長期被銷毀后明顯運行,因為在將 CTRL-C 發送到運行 JAR 的 CMD 窗口時出現以下異常:Exception in thread "Thread-5" org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed我需要做什么才能讓關閉掛鉤仍然能夠訪問實體管理器?我知道這在 Spring / JVM 生命周期中可能為時已晚,因為仍然可以訪問其中任何一個,正確攔截 CTRL-C 調用的替代方法是什么?
1 回答

HUWWW
TA貢獻1874條經驗 獲得超12個贊
看起來我需要的是 SmartLifeCycle 接口的 stop() 方法。它在運行 JAR 的命令提示符下執行 CTRL-C 時被調用,并且仍然可以訪問所有 Spring 的資源,包括 JPA 的實體管理器。唯一的問題是,當此方法執行時,Log4J2 似乎不可用,但這只是一個小麻煩。
添加回答
舉報
0/150
提交
取消