アプリケーションにHttpSessionListenerを登録しています(Grails 1.3.6で記述されたものはSpring3.0.5を使用します)。sessionDestroyedイベントをキャッチし、Springのアプリケーションコンテキストを取得してイベントを公開します。
ApplicationContext getContext(ServletContext servletContext) {
return WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event.getSession());
ApplicationContext context = getContext(event.getSession().getServletContext());
context.publishEvent(e);
}
このコードはほとんどの場合正常に機能します。すべてではありません。アプリケーションがTomcat6で本番環境で実行され、アプリケーションサーバーがシャットダウンした場合、springがコンテキストを閉じ、すべてのBeanを破棄し、コンテキストのclosedプロパティをtrueに設定した後、sessionDestroyedメソッドがHttpSessionDestroyedEventイベントを受け取ります。ただし、コンテキストはまだ存在し、そのpublishメソッドはapplicationEventMulticasterを取得して、このイベントをマルチキャストするように指示します。次に、マルチキャスト担当者は登録済みリスナーのリストを取得し、getBeanを実行して(この時点でBeanFactoryがこのBeanを作成します)、それらを呼び出します。
コンテキストがすでに閉じている場合、マルチキャスト担当者はイベントリスナーへの呼び出しを処理するべきではないようです。この動作により、アプリケーションはシャットダウンステップで実行すべきではないいくつかの作業を実行しました。
コンテキストが閉じられた後、リスナーへの呼び出しを防ぐにはどうすればよいですか?アプリケーションコンテキストに実装されたイベントパブリッシャーは、現在のコンテキストが閉じられていないことを確認しません。