Spring Boot AOPで、メソッド「Around」期間中にクラスアノテーションを取得するにはどうすればよいですか?

Aug 24 2020

ここにいるすべての友達に感謝します。に設定されたアノテーションのアノテーションパラメータを取得する方法を知っていますmethod

Classレベルに注釈を追加したいのですが。ClassAOP Aroundメソッドで属性を取得するにはどうすればよいですか?

私はからの応答値を変更する必要がある理由ところで、私は、別の質問を持っているvoidObjectして復帰pjp.proceed()。メソッドに応答がない場合、リクエストはフリーズします。

HasRoleアノテーションを持つメソッドの場合

@Around("@annotation(com.example.demo.aspect.annotation.HasRole) && @annotation(annotation)")
public void aroundHasRole(ProceedingJoinPoint pjp, HasRole annotation) throws Throwable {

    log.info("value->>{}", annotation.value());
    pjp.proceed();

}

HasRoleアノテーションを持つクラスまたはメソッドの場合

@Around("(@within(com.example.demo.aspect.annotation.IsAdmin)"
        + "|| @annotation(com.example.demo.aspect.annotation.IsAdmin))")
public Object aroundHasRole(ProceedingJoinPoint pjp) throws Throwable {

    <<How to get annotation information here?>>
    return pjp.proceed();

}

回答

2 kriegaex Aug 24 2020 at 08:04

お気づきかもしれませんが、異なる||ブランチからの情報をアドバイスメソッドパラメータにバインドすることはできません。あいまいになるためです。こことここの私の回答も参照してください。したがって、醜い(そして遅い)反射を避けたい場合は、他の回答で推奨したことを実行し、2つの異なるアドバイスを記述して、コードの重複を避けることがここで懸念される場合は、共通コードをヘルパーメソッドに分解します。このようなもの(コード構造についてのアイデアを提供するためだけに、テストされていません):

@Around("@within(annotation)")
public Object classIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  return commonIsAdmin(pjp, annotation);
}

@Around("@annotation(annotation)")
public Object methodIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  return commonIsAdmin(pjp, annotation);
}

public Object commonIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  // Here you would place all common advice code.
  // Non-common code could remain in the original advice methods.
  log.info("value->>{}", annotation.value());
  return pjp.proceed();
}

なぜ私はからの応答値を変更する必要がありvoidObjectと復帰pjp.proceed()。メソッドに応答がない場合、リクエストはフリーズします。

@Beforeまたは@Afterアドバイスとは対照的に、アドバイスでは、@Around呼び出しを行わないことでターゲットメソッドの実行を完全にスキップするかproceed()、の結果を破棄または変更することで、戻り値を変更できますproceed()。返すものは完全に自由です。ターゲットメソッドの戻り値の型と一致する必要があります。

そうは言っても、アラウンドアドバイスメソッドには、インターセプトするターゲットメソッドの戻り値の型と一致する戻り値の型も必要であることが明らかになるはずです。アドバイスが共通のスーパータイプのない多数のタイプを対象としている場合MyTypeは、スーパータイプのような正確なタイプ、または単にObject(すべてのタイプのスーパータイプ)にすることができます。アドバイスは、voidすべてのターゲットメソッドも返す場合(およびその場合のみ)の戻り値の型を持つこともできますvoid(そうでない場合、ポイントカット自体が一致する場合でも、アドバイスはそれらのメソッドと一致しません)。

したがって、アラウンドアドバイスが一致するかどうかは、ポイントカット自体と戻り値の型の組み合わせによって決定されます。これをツールとして使用して、特定の戻り値の型を定義することにより、ポイントカットの一致を制限できます(これにはproceed()proceed()常にを返すため、の戻り値をキャストする必要がありますObject)。

ターゲットメソッドのようなプリミティブ型を返す場合ところで、intbooleanなどを、そしてアドバイスをする結果を自動ラップでしょうIntegerBoolean

ここで見つけることができることをここで説明しているので、SpringAOPとAspectJのマニュアルまたはチュートリアルを読む必要があります。


更新: OPは、パラメーターのバインドに関するドキュメントと、名前の決定方法の説明を求めました。

  • あなたが指定することができますargNames例えば、すべてのアドバイスのタイプ、のためのパラメータを@Before@After@Around
  • そのアノテーションパラメータが存在しない場合、Spring AOPは、コンパイルされている場合、クラスファイルのデバッグ情報を介してアドバイスメソッドのパラメータ名を照合しようとします。そうでない場合、照合は失敗します。
  • Spring AOPの代わりにコンパイル時ウィービングで完全なAspectJを使用する場合、AspectJコンパイラーはコンパイル中に必要な情報を判別できるため、名前の判別はデバッグ情報なしでも機能します。

これらはすべて、SpringAOPのマニュアルで説明されています。

jml940616 Aug 23 2020 at 23:49

リフレクションを介してクラスを取得し、クラスを介して固定メソッド情報を取得し、メソッドのアノテーションを取得します。このように、あなたは反映することができるはずです