MicronautでHTTPクライアントにAOPを適用する方法を解説
生徒
「MicronautのHTTPクライアントにAOPを適用して、リクエスト前後に処理を追加することはできますか?」
先生
「はい、MicronautではHTTPクライアントのインターフェースにAOPアノテーションを付けることで、リクエスト送信前やレスポンス受信後にInterceptorを挟むことができます。」
生徒
「具体的にはどのように設定すればよいですか?」
先生
「順を追って実例を見ながら説明します。HTTP通信の前後でログや監査、共通処理を自動化する方法です。」
1. HTTPクライアントインターフェースを作成
まず、MicronautのHTTPクライアントインターフェースを定義します。@Clientアノテーションを付与することで、指定したURLのAPIと通信するクライアントが自動生成されます。
import io.micronaut.http.annotation.Get;
import io.micronaut.http.client.annotation.Client;
@Client("https://jsonplaceholder.typicode.com")
public interface PostClient {
@Get("/posts/{id}")
String getPost(Long id);
}
2. 独自AOPアノテーションの作成
次にHTTPクライアントに適用する独自AOPアノテーションを作成します。@AroundでInterceptorクラスを指定し、通信の前後に処理を挟むことができます。
import io.micronaut.aop.Around;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
@Around(HttpClientInterceptor.class)
public @interface TimedHttp {
}
3. Interceptorクラスの作成
InterceptorクラスではMethodInterceptorを実装し、context.proceed()の前後に独自処理を追加します。ここでは通信前後のログ出力や処理時間計測を行う例を示します。
import io.micronaut.aop.MethodInterceptor;
import io.micronaut.aop.MethodInvocationContext;
import jakarta.inject.Singleton;
@Singleton
public class HttpClientInterceptor implements MethodInterceptor<Object, Object> {
@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
System.out.println("HTTPリクエスト送信前: " + context.getMethodName());
long start = System.currentTimeMillis();
Object result = context.proceed();
long end = System.currentTimeMillis();
System.out.println("HTTPリクエスト完了: " + context.getMethodName() + " 実行時間: " + (end - start) + "ms");
return result;
}
}
4. クライアントメソッドへのAOP適用
作成した@TimedHttpアノテーションをHTTPクライアントのメソッドに付与します。Interceptorが自動的に実行され、通信前後に処理が挟まれます。
@Client("https://jsonplaceholder.typicode.com")
public interface PostClient {
@TimedHttp
@Get("/posts/{id}")
String getPost(Long id);
}
5. BeanとInterceptorの連携
Interceptor内では他のBeanを@Injectで注入することも可能です。例えば、共通のLoggingServiceやMetricsServiceを注入して、HTTP通信のモニタリングや監査ログを一元管理できます。
import jakarta.inject.Singleton;
import jakarta.inject.Inject;
@Singleton
public class LoggingService {
public void log(String message) {
System.out.println("ログ: " + message);
}
}
@Singleton
public class HttpClientInterceptorWithBean implements MethodInterceptor<Object, Object> {
@Inject
private LoggingService loggingService;
@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
loggingService.log("HTTP通信開始: " + context.getMethodName());
Object result = context.proceed();
loggingService.log("HTTP通信完了: " + context.getMethodName());
return result;
}
}
6. 複数Interceptorの組み合わせ
HTTPクライアントには複数のInterceptorを組み合わせることができます。例えば、タイミング計測用のInterceptorとセキュリティ検証用のInterceptorを同じメソッドに適用し、順序に従って処理を実行できます。
@TimedHttp
@SecurityCheck
@Get("/posts/{id}")
String getPost(Long id);
7. 実務での活用ポイント
HTTPクライアントにAOPを適用すると、通信の前後での共通処理が簡単に追加できます。ログ、監査、エラーハンドリング、リトライ処理などをInterceptorで一元化することで、コードの保守性が向上し、プロジェクト全体で統一した動作が実現できます。