Spring Boot 拡張ポイント徹底解説:モジュール化された柔軟なアーキテクチャの実現
新人エンジニアの田中さんは、ECプラットフォームを構築中、次々と新たな要件が降りtzく:「ログイン時にSMS通知」「支払い完了後のポイント付与」「起動時のキャッシュウォームアップ」……。「これらすべてを既存のサービスクラス内に手動で埋め込む?それは保守性・拡張性の観点で危険です」と Senior Developer は囁きます。答えは Spring Boot の拡張ポイント にあり。
本稿では、システムの腐食を防ぎ、変更に強靭な設計を実現するための主要な拡張メカニズムを、コード例を交えながら隅々まで解説します。
1. 拡張ポイントの意義:結合度の低減と顆粒性の向上
extendability の本質
拡張ポイントとは、アプリケーションの動作ライフサイクル(起動、Bean生成・破棄、イベント処理など)におけるあらかじめ定義されたフックです。ここに独自のロジックを「プラグイン」のように差し込むことで、コア処理とサイドロジックの分離が可能になります。
対比例:
<span class="token comment">/* ❌ 伝統的アプローチ:ロジックが散在し、テスト・保守に脆い */</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserService</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">login</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
validate<span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
updateLastLogin<span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ← ここに「SMS送信」を追加...</span>
smsClient<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ← 「ログ記録」もここに?</span>
auditLog<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"LOGIN"</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ← さらに「ロギング」「カウント更新」...</span>
<span class="token comment">// (コア機能が埋もれる)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/* ✅ 拡張点活用:コア処理と拡張ロジックを明確分離 */</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserService</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> ApplicationEventPublisher<span class="token class-name"> publisher</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token function">UserService</span><span class="token punctuation">(</span>ApplicationEventPublisher publisher<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">publisher</span> <span class="token operator">=</span> publisher<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">login</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
validate<span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
updateLastLogin<span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// イベント発行で拡張ロジックを委譲</span>
publisher<span class="token punctuation">.</span><span class="token function">publishEvent</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">UserAuthenticatedEvent</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// SMS通知は別のコンポーネントとして独立</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SmsNotificationHandler</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> SmsClient smsClient<span class="token punctuation">;</span>
<span class="token keyword">@EventListener</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onUserAuthenticated</span><span class="token punctuation">(</span>UserAuthenticatedEvent event<span class="token punctuation">)</span> <span class="token punctuation">{</span>
smsClient<span class="token punctuation">.</span><span class="token function">sendLoginAlert</span><span class="token punctuation">(</span>event<span class="token punctuation">.</span><span class="token function">getUser</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
この手法により、次のようなメリットが得られます:
- 疎結合:各拡張ロジックは独立して変更・テスト可能。
- 再利用性:同じイベントを複数コンポーネントで購読可能。
- テスト容易性:コアロジックと拡張ロジックの単体テストが容易。
- 迷子 없는 機能開発:「どこにコードを書けば良い?」という設計迷子を解消。
2. 起動時拡張:ライフサイクルフックを活用する
ApplicationListener & ApplicationReadyEvent
Spring Boot アプリケーションが起動し、すべての Bean が初期化・依存関係解決された後、HTTPリスナーが有効になる前後に実行されるイベントです。
典型的用途: キャッシュ事前warm up、非同期タスクの起動、外部依存サービスのヘルスチェック。
<span class="token keyword">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PostStartupInitializer</span> <span class="token keyword">implements</span> ApplicationListener<span class="token.documentation"><</span>ApplicationReadyEvent<span class="token punctuation">;</span><span class="token punctuation">></span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> CacheWarmupService <span class="token function">warmupService</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> HealthChecker <span class="token function">healthChecker</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token function">PostStartupInitializer</span><span class="token punctuation">(</span>CacheWarmupService warmupService<span class="token punctuation">,</span> HealthChecker healthChecker<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">warmupService</span> <span class="token operator">=</span> warmupService<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">healthChecker</span> <span class="token operator">=</span> healthChecker<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onApplicationEvent</span><span class="token punctuation">(</span>ApplicationReadyEvent event<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">log</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"Startup hooks triggered..."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 非同期で並列処理可能</span>
<span class="token punctuation">;</span>
<span class="token comment">// 1. キャッシュウォームアップ</span>
warmupService<span class="token punctuation">.</span><span class="token function">prewarmAllCategories</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2. 外部依存サービス監視</span>
healthChecker<span class="token punctuation">.</span><span class="token function">checkDependenciesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 3. メトリック登録</span>
Metrics<span class="token punctuation">.</span><span class="token function">registerStatus</span><span class="token punctuation">(</span><span class="token string">"app_initialized"</span><span class="token punctuation">,</span> <span class="token keyword">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
ApplicationRunner:明示的な引数による初期化
CommandLineRunnerの進化版で、ApplicationArgumentsを通じて解析されたコマンドライン引数(オプション・非オプション)を型安全に扱えます。
<span class="token keyword">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfigurationLoader</span> <span class="token keyword">implements</span> ApplicationRunner <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> ConfigRepository <span class="token function">configRepo</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token function">ConfigurationLoader</span><span class="token punctuation">(</span>ConfigRepository configRepo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">configRepo</span> <span class="token operator">=</span> configRepo<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span>ApplicationArguments args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>args<span class="token punctuation">.</span><span class="token function">containsOption</span><span class="token punctuation">(</span><span class="token string">"config-level"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
String <span class="token function">level</span> <span class="token operator">=</span> args<span class="token punctuation">.</span><span class="token function">getOptionValues</span><span class="token punctuation">(</span><span class="token string">"config-level"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">log</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"Loading config with level: {}"</span><span class="token punctuation">,</span> level<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">switch</span> <span class="token punctuation">(</span>level<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">case</span> <span class="token string">"FULL"</span> <span class="token operator">-></span> configRepo<span class="token punctuation">.</span><span class="token function">loadAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">case</span> <span class="token string">"MINIMAL"</span> <span class="token operator">-></span> configRepo<span class="token punctuation">.</span><span class="token function">loadEssentials</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">default</span> <span class="token operator">-></span> <span class="token function">log</span><span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"Unknown config level: {}"</span><span class="token punctuation">,</span> level<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
CommandLineRunner:軽量な起動時スクリプト
String... argsをそのまま受け取り、@Orderで実行順を制御します。単純な初期化処理やデータseedに最適。
<span class="token keyword">@Component</span>
<span class="token keyword">@Order</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DatabaseMigrator</span> <span class="token keyword">implements</span> CommandLineRunner <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> Flyway flyway<span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token function">DatabaseMigrator</span><span class="token punctuation">(</span>Flyway flyway<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">flyway</span> <span class="token operator">=</span> flyway<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span>String<span class="token punctuation">...</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">log</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"Running Flyway migrations..."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
flyway<span class="token punctuation">.</span><span class="token function">migrate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">log</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"Migration completed."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
3. Bean生成ライフサイクルの拡張
BeanPostProcessor:Bean生成をフックする最強のフック
Springフレームワークのコア拡張ポイント。Beanのインスタンス生成後・初期化前/後の両段階で介入可能です。AOPや
プロキシ生成、アノテーション駆動のDIアーキテクチャはすべてこのインターフェースで実装されています。
<span class="token keyword">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AspectEnricher</span> <span class="token keyword">implements</span> BeanPostProcessor <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> BeanFactory beanFactory<span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token function">AspectEnricher</span><span class="token punctuation">(</span>BeanFactory factory<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">beanFactory</span> <span class="token operator">=</span> factory<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Override</span>
<span class="token keyword">public</span> Object <span class="token function">postProcessBeforeInitialization</span><span class="token punctuation">(</span>Object bean<span class="token punctuation">,</span> String beanName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// @Timed 注釈付與Beanに対してメトリクス計測プロキシを適用</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>bean<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">()</span><span class="token punctuation">.</span><span class="token function">isAnnotationPresent</span><span class="token punctuation">(</span>Timed<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">log</span><span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Applying timing aspect to: {}"</span><span class="token punctuation">,</span> beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> Proxy<span class="token punctuation">.</span><span class="token function">newProxyInstance</span><span class="token punctuation">(</span>
bean<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">()</span><span class="token punctuation">.</span><span class="token function">getClassLoader</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
bean<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">()</span><span class="token punctuation">.</span><span class="token function">getInterfaces</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">(</span>proxy<span class="token punctuation">,</span> method<span class="token punctuation">,</span> args<span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> start <span class="token operator">=</span> System<span class="token punctuation">.</span><span class="token function">nanoTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> method<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>bean<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">finally</span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> elapsed <span class="token operator">=</span> System<span class="token punctuation">.</span><span class="token function">nanoTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> start<span class="token punctuation">;</span>
Metrics<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span>beanName <span class="token operator">+</span> <span class="token string">"."</span> <span class="token operator">+</span> method<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">record</span><span class="token punctuation">(</span>elapsed<span class="token punctuation">,</span> TimeUnit<span class="token punctuation">.</span>NANOSECONDS<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> bean<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Override</span>
<span class="token keyword">public</span> Object <span class="token function">postProcessAfterInitialization</span><span class="token punctuation">(</span>Object bean<span class="token punctuation">,</span> String beanName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// @CircuitBreaker 付きBeanに対してリトライ・フォールバック機構を追加</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>bean<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">()</span><span class="token punctuation">.</span><span class="token function">isAnnotationPresent</span><span class="token punctuation">(</span>CircuitBreaker<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">log</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"Wrapping fallback handler: {}"</span><span class="token punctuation">,</span> beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> buildFallbackProxy<span class="token punctuation">(</span>bean<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> bean<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
InitializingBean & DisposableBean:リソース管理の明示的フック
コネクションプールやスケジューラーなど、明確な初期化・終了サイクルを持つリソースを自動管理するための純粋なライフサイクルコールバックです。
<span class="token keyword">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ScheduledTaskManager</span> <span class="token keyword">implements</span> InitializingBean<span class="token punctuation">,</span> DisposableBean <span class="token punctuation">{</span>
<span class="token keyword">private</span> ScheduledExecutorService scheduler<span class="token punctuation">;</span>
<span class="token keyword">private</span> List<span class="token punctuation"><</span>Runnable<span class="token punctuation">;</span><span class="token punctuation">></span> tasks<span class="token punctuation">;</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">afterPropertiesSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
scheduler <span class="token operator">=</span> Executors<span class="token punctuation">.</span><span class="token function">newScheduledThreadPool</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
tasks <span class="token operator">=</span> List<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>
<span class="token keyword">new</span> <span class="token class-name">ReportGenerator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">CleanupJob</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
tasks<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>task <span class="token operator">-></span> scheduler<span class="token punctuation">.</span><span class="token function">scheduleAtFixedRate</span><span class="token punctuation">(</span>task<span class="token punctuation">,</span>
<span class="token number">0</span><span class="token punctuation">,</span> <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">log</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"{} scheduled tasks started."</span><span class="token punctuation">,</span> tasks<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">;</span>
<span class="token keyword">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">destroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
tasks<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>scheduler<span class="token punctuation">:</span><span class="token operator">:</span><span class="token function">cancel</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
scheduler<span class="token punctuation">.</span><span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>scheduler<span class="token punctuation">.</span><span class="token function">awaitTermination</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> TimeUnit<span class="token punctuation">.</span>SECONDS<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
scheduler<span class="token punctuation">.</span><span class="token function">shutdownNow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>InterruptedException e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
scheduler<span class="token punctuation">.</span><span class="token function">shutdownNow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Thread<span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">()</span><span class="token punctuation">.</span><span class="token function">interrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>