春のダーク馬:AOPの通知タイプ

ファイブ0予告

事前通知:ポイントカットは、メソッドを実行する前に行う、
ポスト通知:この方法は、実行するための通常のエントリポイントの後に行われます。それは今まで一つの例外通知を実行することができます。
例外通知:エントリポイントメソッドが例外を実施した後に実行されます。また、予告を投稿しか実行することができ、
最終通告:それを実行するための通常のエントリポイント法はその背中を実行するかどうかは関係ありません。

アドバイスアラウンド図4は、書面による通知が含まれ、通知は一般的にサラウンドあります結果は少し異なっているので。

  • ProceedingJoinPoint:Springフレームワークは、インターフェイスを提供してくれます。インターフェース)は(続行する方法があり、この方法は、明示的エントリポイントメソッドを呼び出すことと等価です。
  • インターフェイスは、Springフレームワークは、私たちは私たちのために使用するためのインタフェースの実装クラスを提供します。、プログラムの実行中に、囲まれたパラメータとして通知することができます
  • サラウンド通知方法および通知タイプ4、図があるポイントカット。
    ここに画像を挿入説明

1.bean.xml構成

  • (1)ではAOP:ポイントカット式が書かれた(ポイントカットラベル内の公共切断面)、通知の様々な種類を、次のことは、このポイントカット式を呼び出すことができます。
  • (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
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置spring的IOC,把service对象配置进来-->
    <bean id="accountService" class="com.jh.service.impl.AccountServiceImpl"></bean>

    <!--配置Logger类-->
    <bean id="logger" class="com.jh.utils.Logger"></bean>

    <!--配置AOP-->
    <aop:config>
        <!-- 配置切入点简便表达式:id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容
             此标签写在aop:aspect标签内部只能当前切面使用。
             它还可以写在aop:aspect外面,此时就变成了所有切面可用,必须写在前面(配置AOP的顺序)
         -->
        <aop:pointcut id="pt1" expression="execution(* com.jh.service.impl.*.*(..))"></aop:pointcut>
        <!--配置切面-->
        <aop:aspect id="logAdvice" ref="logger">
            <!--配置前置通知:在切入点方法执行之前执行-->
            <aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>
            <!--配置后置通知:在切入点方法正常执行之后执行。它和异常通知永远只能执行一个-->
            <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>
            <!--配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个-->
            <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>
            <!--配置最终通知:无论切入点方法是否正常执行它都会在其后面执行-->
            <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>
            <!-- 配置环绕通知 详细的注释请看Logger类中-->
           <aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>
        </aop:aspect>
    </aop:config>
</beans>

図:ここに画像を挿入説明


変化に対する各層の2. XML構成

サービス:インタフェース変化なし
サービス:実装クラス

package com.jh.service.impl;
import com.jh.service.IAccountService;
/**
 * 账户的业务层实现类
 * */
public class AccountServiceImpl implements IAccountService {
    @Override
    public void saveAccount() {
        System.out.println("执行了保存");
        //int i=1/0;
        /**结果:
         * 前置通知Logger类中的beforePrintLog方法开始记录日志了。。。
         * 执行了保存
         * 异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。
         * 最终通知Logger类中的afterPrintLog方法开始记录日志了。。。
         * */
    }

    @Override
    public void updateAccount(int i) {
        System.out.println("执行了更新操作:"+i);
    }

    @Override
    public int deleteAccount() {
        System.out.println("执行了删除");
        return 0;
    }
}

ときのSystem.out.printlnは(「保存」);次の例外の文intの存在は、私は1/0 =;ときに通常出力文。
:(結果異常通知と事後通知が共存することはできません

前置通知Logger类中的beforePrintLog方法开始记录日志了。。。
执行了保存
异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。
最终通知Logger类中的afterPrintLog方法开始记录日志了。。。

utilsの:Loggerクラスの予告

 package com.jh.utils;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 用于记录日志的工具类,它里面提供了公共的代码
* */
public class Logger {
  /**前置通知*/
  public  void beforePrintLog(){
      System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了。。。");
  }

  /**后置通知*/
  public  void afterReturningPrintLog(){
      System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志了。。。");
  }

  /**异常通知*/
  public  void afterThrowingPrintLog(){
      System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。");
  }

  /**最终通知*/
  public  void afterPrintLog(){
      System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。");
  }

  /**
   * 环绕通知
   * 问题:当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了。
   * 分析:
   *通过对比动态代理中的环绕通知代码,发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有。
   * 解决:
   * Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法。
   *该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。
   * spring中的环绕通知:
   *    它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。
   * */
  public Object aroundPrintLog(ProceedingJoinPoint pjp){
      Object rtValue=null;
      try {
          Object[] args=pjp.getArgs();//得到方法执行所需的参数
          System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。。前置");
          rtValue=pjp.proceed(args);//明确调用业务层方法(切入点方法)
          System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。。后置");
          return rtValue;
      } catch (Throwable t) {
          System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。。异常");
         throw new RuntimeException(t);
      } finally {
          System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");
      }
  }
}

一般的にだけでサラウンド結果通知:

開始をログに記録する方法aroundPrintLog Loggerクラス。フロント
aが保存
aroundPrintLogメソッドLoggerクラスログを開始します。リア
開始をロギングaroundPringLog方法Loggerクラス。決勝


テストクラスAOPTest

package com.jh.test;
import com.jh.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**测试AOP的配置*/
public class AOPTest {
    public static void main(String[] args) {
        //1.获取容器
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取service bean对象
        IAccountService as=(IAccountService)ac.getBean("accountService");
        //3.执行方法
        as.saveAccount();
    }
}

4つの結果手書き :(通常のみ3を実行し、リア投げアドバイスは存在しません)

事前通知LoggerクラスのためのBeforePrintLog方法は、ログを開始します。
Aは、保存し
、最終的な通知afterPrintLog方法Loggerクラスは、ロギングを開始します。
開始をログに記録する通知afterReturningPrintLogリアLoggerクラスのメソッド。

:結果は、4話の異なるサラウンド予告してい
アラウンドアドバイスが最後に最終通告され、それは一般的なアドバイスを中心に使用されています。

公開された101元の記事 ウォン称賛15 ビュー6765

おすすめ

転載: blog.csdn.net/JH39456194/article/details/104435238