ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
@After とは
Spring AOP の @After アノテーションは、対象メソッドの実行が終了した後に共通処理を挟みます。ログ出力・リソース解放・統計収集など、横断的関心事をビジネスロジックから分離できます。
基本構文
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@After("execution(* com.example.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
log.info("[AFTER] {} が完了", methodName);
}
}
これだけで com.example.service パッケージ配下のすべての public メソッドの実行後に logAfter が呼ばれます。
@Before / @After / @AfterReturning / @AfterThrowing / @Around の違い
| アノテーション | 実行タイミング | 例外時 | 戻り値取得 |
|---|---|---|---|
| @Before | メソッド実行前 | 例外有無無関係に実行 | ×(実行前なので戻り値なし) |
| @After | メソッド実行後(finally 的) | ○ 例外時も実行 | × |
| @AfterReturning | 正常終了後のみ | × 例外時はスキップ | ○ returning 属性で取得 |
| @AfterThrowing | 例外発生時のみ | ○(その例外時のみ) | 例外オブジェクト取得 |
| @Around | 前後両方(最も柔軟) | 制御可能 | ○ 自分で proceed() を呼ぶ |
各アノテーションの実装例
@Aspect
@Component
public class CompleteAspect {
// 前処理: メソッド実行前
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice(JoinPoint jp) {
log.info("[BEFORE] {} を実行", jp.getSignature().getName());
}
// 後処理 (finally 的): 必ず実行
@After("execution(* com.example.service.*.*(..))")
public void afterAdvice(JoinPoint jp) {
log.info("[AFTER] {} 完了 (正常 or 例外)", jp.getSignature().getName());
}
// 正常終了時のみ
@AfterReturning(
pointcut = "execution(* com.example.service.*.*(..))",
returning = "result"
)
public void afterReturning(JoinPoint jp, Object result) {
log.info("[AFTER_RETURNING] {} 正常終了, 戻り値: {}",
jp.getSignature().getName(), result);
}
// 例外発生時のみ
@AfterThrowing(
pointcut = "execution(* com.example.service.*.*(..))",
throwing = "ex"
)
public void afterThrowing(JoinPoint jp, Exception ex) {
log.error("[AFTER_THROWING] {} で例外: {}",
jp.getSignature().getName(), ex.getMessage());
}
// 前後両方を制御
@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
Object result = pjp.proceed(); // 元メソッドを実行
long elapsed = System.currentTimeMillis() - start;
log.info("[AROUND] {} 完了 ({}ms)", pjp.getSignature().getName(), elapsed);
return result;
} catch (Throwable t) {
log.error("[AROUND] {} 失敗", pjp.getSignature().getName());
throw t;
}
}
}
実行順序
1 メソッドに複数の Advice がマッチする場合の順序:
@Before
↓
@Around (前半)
↓
[ 対象メソッド実行 ]
↓
@Around (後半)
↓
@After
↓
@AfterReturning (正常時) または @AfterThrowing (例外時)
ポイントカット式の書き方
| 式 | 意味 |
|---|---|
execution(* com.example.service.*.*(..)) | service パッケージの全クラスの全 public メソッド |
execution(* *Service.find*(..)) | Service で終わるクラスの find で始まるメソッド |
@annotation(org.springframework.transaction.annotation.Transactional) | @Transactional 付きメソッド |
within(com.example.service.*) | service パッケージ内のメソッド呼び出しすべて |
@within(org.springframework.stereotype.Service) | @Service クラスの全メソッド |
this(com.example.MyInterface) | MyInterface 実装クラス |
args(java.lang.String, ..) | 第 1 引数が String のメソッド |
カスタムアノテーション + AOP
独自アノテーションを作って AOP のターゲット指定に使うパターン:
// 1. カスタムアノテーション定義
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
String value() default "";
}
// 2. AOP で受ける
@Aspect
@Component
public class LogExecutionTimeAspect {
@Around("@annotation(LogExecutionTime)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
return pjp.proceed();
} finally {
long elapsed = System.currentTimeMillis() - start;
log.info("{} took {}ms", pjp.getSignature().getName(), elapsed);
}
}
}
// 3. 使い方
@Service
public class UserService {
@LogExecutionTime
public List findAll() {
// ... 処理(自動的に時間が計測される)
}
}
JoinPoint の主要メソッド
@After("execution(* com.example..*(..))")
public void after(JoinPoint jp) {
// メソッド名
String name = jp.getSignature().getName();
// クラス名
String className = jp.getTarget().getClass().getName();
// メソッド引数
Object[] args = jp.getArgs();
// シグネチャ
Signature sig = jp.getSignature();
// 例: "void com.example.UserService.save(User)"
log.info("Called {} with args {}", sig, Arrays.toString(args));
}
有効化: @EnableAspectJAutoProxy
Spring Boot では自動で有効化されますが、Spring Framework(非 Boot)では明示が必要:
@Configuration
@EnableAspectJAutoProxy // ★ AOP 有効化
@ComponentScan("com.example")
public class AppConfig {
}
注意点
- 同一クラス内のメソッド呼び出しでは AOP が効かない:
this.someMethod()はプロキシを経由しないため - private / final メソッドは AOP 対象外
- パフォーマンスへの影響: プロキシ経由になるので極端なホットパスは慎重に
- 順序制御: 複数の Aspect 間の順序は
@Order(数値)で制御(小さい数値が先) - ログ出力ループ: AOP の中で対象クラスのロガーを呼ぶと無限ループのリスク
典型的な用途
- ログ・監査: メソッド呼び出しの自動記録
- パフォーマンス計測: 実行時間の収集
- トランザクション境界:
@Transactional自体が AOP 実装 - キャッシュ:
@Cacheableも AOP ベース - セキュリティ:
@PreAuthorize認可チェック - リトライ: Spring Retry の
@Retryable - Circuit Breaker: Resilience4j のアノテーション
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Laravel キャッシュクリア完全ガイド(cache:clear / config:clear / 2026-05-18 07:42:07
- プロジェクトの作成と削除 2026-05-18 07:42:07
- インストール直後にNetbeansが反応しない 2026-05-18 07:42:07
- 動画やチャンネルの検索 2026-05-18 07:42:07
- APIキー取得方法 2026-05-18 07:42:07
- チャンネル情報の取得 2026-05-18 07:42:07
- API 入門 — Web API(REST / GraphQL / gRPC / 2026-05-18 07:42:07
- インストール(eclipseプラグイン) 2026-05-18 07:42:07
- Laravel「Dotenv values containing spaces must be surrounded 2026-05-18 07:42:07
- エラー一覧 2026-05-18 07:42:07
- curl: (51) SSL: certificate subject name '~' does not match 2026-05-18 07:42:07
- インストール方法(Windows版) 2026-05-18 07:42:07
- JSONから配列に変換 2026-05-18 07:42:07
- 処理を一定時間待つ 2026-05-18 07:42:07
- A non well formed numeric value encountered 2026-05-18 07:42:07
コメントを削除してもよろしいでしょうか?