Spring 6 [異常通知、複数の同一通知の実行順序を含むスキーマベースの方法、AspectJによるAOP実装、通知内のエントリポイントパラメータ取得の書き方](15) - 徹底詳細解説(学習まとめ --- エントリーより)深化へ)

目次

例外通知

スキーマベースのメソッドには、複数の同一通知の実行順序が含まれます。

AspectJ は AOP を実装します

通知内のポイントカットパラメータを取得する方法 

 純粋なアノテーション モードで AOP を実現する


6. 例外通知

例外通知は、ポイントカットで例外が発生した場合にのみトリガーされます。メソッド内に例外がない場合、例外通知は実行されません。

6.1 新しい通知クラスの作成

新しい com.tong.advice.MyThrow を作成します。

MethodInterceptor インターフェイスにはメソッドがありませんが、次のメソッドのいずれかを厳密に提供する必要があります。

  • public void afterThrowing: 同じでなければなりません
  • 例外パラメータが必要です 

つまり、ThrowsAdvice にはメソッドがありませんが、以下のようなメソッドを記述する必要があります。

package com.tong.advice;
import org.springframework.aop.ThrowsAdvice;
public class MyThrow implements ThrowsAdvice {
     public void afterThrowing(Exception e){
         System.out.println("异常通知:"+e.getMessage());
    }
}

 6.2 構成の側面

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

     <context:component-scan base-package="com.tong.mapper,com.tong.service.impl"> 
     </context:component-scan>
     <bean id="mybefore" class="com.tong.advice.MyBefore"></bean>
     <bean id="myafter" class="com.tong.advice.MyAfter"></bean>
     <bean id="myaround" class="com.tong.advice.MyAround"></bean>
     <!-- 异常通知 -->
     <bean id="mythrow" class="com.tong.advice.MyThrow"></bean>
     <aop:config>
        <aop:pointcut id="mypoint" expression="execution(*
com.tong.service.impl.PeopleServiceImpl.test())"/>
        <!-- 织入异常通知 -->
       <aop:advisor advice-ref="mythrow" pointcut-ref="mypoint"></aop:advisor>
    </aop:config>
</beans>

6.3 ポイントカットに例外を記述する

PeopleServiceImpl で例外を引き起こすコードを作成します。

@Service("peopleService")
public class PeopleServiceImpl implements PeopleService {
    @Autowired
    private PeopleMapperImpl peopleMapperImpl123;
    @Override
    public void test() {
        System.out.println("join pointer 切入点。");
        int i = 5/0;// 算数异常
    }
}

7. スキーマベースのメソッドには、複数の同一通知の実行順序が含まれます。

アスペクトに複数のアドバイスが含まれている場合、実行順序は構成順序に従います。

  • 事前通知: 最初の構成が最初に実行されます
  • 通知後: 最初に構成してから実行します
  • サラウンド通知: 最初に設定された通知が最初に実行され、その後終了します。
  • 例外通知: 構成後に実行 (ThrowsAdvice は AfterAdvice のサブインターフェイスであり、AfterReturningAdvice は AfterAdvice のサブインターフェイスです)

AspectJ は AOP を実装します

1. AspectJ の概要

先ほど学習したスキーマベースの手法は、Spring フレームワークが提供する AOP 実装手法に属します。

AspectJ は Spring フレームワークによって提供されるテクノロジではなく、Java AOP フレームワークであり、Java バイトコード ファイルを生成する特別なコンパイラの助けを借りて、コンパイル後に対応するアスペクトが形成されます。言い換えれば、AspectJ はコンパイル時の拡張機能です。

Spring Framework 2.0 では、AspectJ メソッドのサポートが開始されました。

注釈または XML 構成ファイルを使用できます。

AspectJ の方法は非常に簡単で、アドバイスのパラメータに関係なく、POJO と特定の設定を使用するだけです。ただし、パラメーターの問題や通知の戻り値を考慮する必要がある場合、相対的な構成はより複雑になります。

2. AspectJ 通知タイプ

  1. 事前通知
  2. 通知を投稿する:
  •         後で例外が発生したかどうかに関係なく実行される事後通知。
  •         復帰後通知は復帰後のエントリポイントに例外がない場合にのみ実行されます。

    3.周囲のサラウンド通知

    4. 投擲後の異常通知

3. コードの実装

3.1 通知クラスの作成

Aspectj で AOP 通知クラスを実装する方法では、インターフェイスを実装する必要はありません。共通の Java クラスを直接宣言し、クラス内で通知メソッドを直接定義するだけです。メソッド名は任意ですが、メソッド名は次のとおりにすることをお勧めします。名前でおなじみ。

package com.tong.advice;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAdvice {
     //前置通知方法
     public void before(){
          System.out.println("我是前置通知方法...");
     }
     //后置通知方法
     public void after(){
          System.out.println("我是后置通知方法...");
     }
     //环绕通知方法
     public Object round(ProceedingJoinPoint pp) throws Throwable {
          System.out.println("环绕---前");
          //放行
          Object proceed = pp.proceed();
          System.out.println("环绕---后");
          return proceed;
     }
     //异常通知方法
     public void myThrow(Exception ex){
         System.out.println("我是异常通知......"+ex.getMessage());
    }
}

3.2 AOP の構成

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">
      <!--配置真实对象的bean-->
      <bean id="us" class="com.tong.service.impl.UserServiceImpl"></bean>
      <!--配置通知bean-->
      <bean id="advice" class="com.tong.advice.MyAdvice"></bean>
      <!--配置AOP组装-->
      <aop:config>
          <!--基于Aspectj方式配置-->
          <aop:aspect ref="advice">
          <!--声明切点-->
          <aop:pointcut id="mp" expression="execution(* com.tong.*.impl.*.*(..))"/>
          <!--配置通知方法-->
          <aop:before method="before" pointcut-ref="mp"></aop:before>
          <!--切点正常执行才会被执行-->
          <aop:after-returning method="after" pointcut-ref="mp"></aop:afterreturning>
          <!--切点是否正常执行都会执行-->
          <!--<aop:after method="after" pointcut-ref="mp"></aop:after>-->
          <aop:around method="round" pointcut-ref="mp"></aop:around>
          <!-- 必须使用throwing声明异常参数名 -->
          <aop:after-throwing method="myThrow" pointcut-ref="mp" throwing="ex"> 
          </aop:after-throwing>
          </aop:aspect>
       </aop:config>
</beans>

知らせ:

復帰後と復帰後とは、復帰後はポイントカットポイントが異常であるか否かに関係なく実行される事後通知であり、復帰後はポイントカットポイントが正常に実行された場合にのみ実行される通知である。

3. 通知内のポイントカットパラメータの記述方法を取得する 

package com.tong.advice;
import org.aspectj.lang.ProceedingJoinPoint;
/*
如果希望获取切入点方法的参数,推荐把通知的参和切入点的参数写成一致。
*/
public class MyAdvice2 {
       public void mybefore(int id1, boolean bool1){
             System.out.println("前置通知"+id1+","+bool1);
       }

       public void myafter(int id1, boolean bool1){
             System.out.println("后置:"+id1+","+bool1);
       }

       public void myafter2(int id1, boolean bool1){
             System.out.println("后置2:"+id1+","+bool1);
       }
       
       public Object myaround(ProceedingJoinPoint pjp,int id1, boolean bool1)
throws Throwable {
             System.out.println("环绕前置");
             Object result = pjp.proceed();
             System.out.println("环绕后置");
             return result;
       }
      public void mythrow(Exception e,int id1, boolean bool1){
           System.out.println("异常通知:"+e.getMessage()+",id:"+id1+",bool1:"+bool1);
     }
}

設定ファイルで設定する

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

      <context:component-scan base-package="com.tong.mapper,com.tong.service.impl"> 
      </context:component-scan>
      <bean id="myadvice2" class="com.tong.advice.MyAdvice2"></bean>
         <aop:config>
            <!-- ref引用自定义通知类对应bean的id -->
            <aop:aspect ref="myadvice2">
            <!-- args写在execution括号外面 -->
                <!-- args括号内的名称和通知中方法参数名相同-->
                <aop:pointcut id="mypoint" expression="execution(* com.tong.service.impl.PeopleServiceImpl.test(int,boolean)) and args(id1,bool1)"/>
               <aop:before method="mybefore" pointcut-ref="mypoint" arg-names="id1,bool1"></aop:before>
               <aop:after-returning method="myafter" pointcut-ref="mypoint" arg-names="id1,bool1"></aop:after-returning>
               <aop:after method="myafter2" pointcut-ref="mypoint" arg-names="id1,bool1"> 
               </aop:after>
               <!-- names里面取值要和通知中方法参数名完全一致。pjp由Spring帮助自动注入进来 --
>
              <aop:around method="myaround" pointcut-ref="mypoint" argnames="pjp,id1,bool1" ></aop:around>
               <!-- 不要忘记通过throwing属性声明异常参数名称-->
               <aop:after-throwing method="mythrow" pointcut-ref="mypoint" argnames="e,id1,bool1" throwing="e"></aop:after-throwing>
        </aop:aspect>
    </aop:config>
</beans>

4. スキーマベースと Aspectj の違い

スキーマベース: スキーマベース。インターフェースに基づいて実装されます。通知の種類を決定するには、各通知で特定のインターフェイス タイプを実装する必要があります。クラスにはすでにインターフェイスが実装されているため、構成は比較的簡単です。特に、設定でパラメータと戻り値の型を指定する必要はありません。

AspectJ 方式: 設定に基づいて実装されます。さまざまな設定タグを通じて Spring にアドバイスの種類を伝えます。AspectJ のアプローチは、アドバイス クラス用に記述するのがより簡単です。ただし、パラメータと戻り値は設定ファイルで特別に設定する必要があります。

Scheme ベースは実行時の拡張機能であるため、AspectJ はコンパイル時の拡張機能です。したがって、アスペクトが少なくても、パフォーマンスに大きな違いはありません。ただし、多くのアスペクトがある場合は、AspectJ メソッドの方がはるかに高速であるため、AspectJ メソッドを選択するのが最善です。

Schema-based是Spring框架自己的AOP实现。而AspectJ属于Spring框架对AspectJ的集成支持。

 純粋なアノテーション モードで AOP を実現する

1. 全体的な構成手順

Spring フレームワークでは、AOP アノテーションは AspectJ アノテーションのみをサポートします。注釈を使用して AspectJ スタイルの XML 構成を簡素化します。XML+ アノテーションを通じて AOP を実装することも、純粋なアノテーションを使用して AOP を実装することもできます。

1.1 XML+ アノテーション

XML+ 注釈を使用して AOP を実装する場合は、applicationContext.xml 構成ファイルを作成し、注釈スキャンを有効にし、AOP 注釈を有効にする必要があります。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">
      
        <!--配置注解扫描路径:-->
        <context:component-scan base-package="com.tong.annotation">
        </context:component-scan>
            <!--配置AOP注解生效-->
            <aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
</beans>

次に、テスト クラスで、location 属性を使用して構成ファイルをロードします。

@SpringJUnitConfig(locations = "classpath:applicationContext.xml")
public class AnnotationTest {}

1.2 純粋なアノテーション方法

純粋なアノテーション メソッドを使用する場合、実際には Java Config メソッドを使用して applicationContext.xml を構成クラスに置き換えます。

@Configuration
// 等效于<context:component-scan base-package="com.tong.annotation">
@ComponentScan("com.tong.annotation")
// 等效于<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
@EnableAspectJAutoProxy
public class AnnotationConfig {}

次に、テスト クラスで、classes 属性を使用して構成クラスをロードします。

@SpringJUnitConfig(classes = AnnotationConfig.class)
public class AnnotationTest {}

おすすめ

転載: blog.csdn.net/m0_58719994/article/details/132000975
おすすめ