AspectJベースSpring AOP Advice実行順


前言
Springで開発したことがある学生は、SpringのAOPについて多少の知識と使用経験がある.@Around,@Before,@AfterなどのAdviceも知られている.Spring AOPの基本概念については、皆さんもよく知っていると思いますが、ここではもう説明しません.
今日フォーラムの中で1つの問題を見て、Spring AOPのAdviceの実行順序の問題について話して、問題を見た後に、突然自分がこの方面に対する理解もあまり深くないことに気づきました.質問に答えると同時に、ちょうどこの知識点を深く理解した.
ここではSpring AspectJ AOP方式に基づいて説明する.
Spring公式のAdvice実行順序の解釈
参考ドキュメント:aop-ataspectj-advice-ordering
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined. You can control the order of execution by specifying precedence. This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the Order annotation. Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.
以上のように簡単に説明すると、同じJoin Pointに対して2つのAdviceが異なるAspectに定義されている場合、それらの実行順序は、Aspectクラスの@Order注記の値、またはOrderを実現するgetValueメソッドの値を書き換えることによって決定される.また、Orderの値が小さいほど優先度が高くなる.
When two pieces of advice defined in the same aspect both need to run at the same join point, the ordering is undefined
同じAspectの中で同じJoin Pointに対して2つのAdviceがある場合、この2つのAdviceの順序は固定されない.
≪インスタンス|Instance|emdw≫
まずSpringのプロジェクトを構築し、spring-testに基づいて次の操作を行います.この文書のspringバージョンは4.3.11です.RELEASE
1.メソッドに作用するAuthAnnotation注記クラスを作成する
2.springの構成にaspect aopサポートを追加する

3.AspectのAdviceを作成します.図の赤い枠の方法名に注意してください.
4.サービスを作成し、上の切り込みポイントルールに合致すればよい
5.ユニットテストを実行し、TestServicesを呼び出す.test()メソッド、出力結果は以下の通りです.
----Order1:checkAuth:Annotation----
----Order1:checkAuthPackage:Execution----
----Order2:checkAuthPackage:Execution----
---Service:Test---

複数回実行すると、Order 1のcheckAuthメソッドが最初に実行されているという問題が発見されます.これは、注記方式のPointCutが最初に実行される優先度があるかどうかを示していますか?もしそうなら、上のSpring公式ドキュメントの言い方には合いません.なぜか見てみましょう
ReflectiveAspectJAdvisorFactory
このクラスの役割はAspectJに基づいてSpring AOPのAdviceを作成することである.
static {
        CompoundComparator comparator = new CompoundComparator();
        comparator.addComparator(new ConvertingComparator(
                new InstanceComparator(
                        Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
                new Converter() {
                    @Override
                    public Annotation convert(Method method) {
                        AspectJAnnotation> annotation =
                                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
                        return (annotation != null ? annotation.getAnnotation() : null);
                    }
                }));
        comparator.addComparator(new ConvertingComparator(
                new Converter() {
                    @Override
                    public String convert(Method method) {
                        return method.getName();
                    }
                }));
        METHOD_COMPARATOR = comparator;
    }

このクラスの静的方法ブロックから、Adviceリストの追加順序は、Around/Before/After/AfterReturning/AfterThrowingの順序であるとともに、Adviceの方法名順で並べ替えられることがわかる.
getAdvisorsメソッドを呼び出すと、getAdvisorMethodsメソッドが呼び出され、すべてのadvice Methodオブジェクトが取得する.同時にMETHOD_によるCOMPARATORのルールをソートする.
最後のテスト
OrderOneAspectクラスでは、checkAuthPackageメソッドの名前がaCheckAuthPackageであり、セルテストを実行した結果は次のようになります.
----Order1:checkAuthPackage:Execution----
----Order1:checkAuth:Annotation----
----Order2:checkAuthPackage:Execution----
---Service:Test---

出力の結果,優先的に実行するのは注釈方式のPonitCutではないことがわかる.このように、同一のAspectにおいて同一のJoin Pointに対して2つのAdviceがある場合、実行の順序はメソッドの名称に関係する.