首頁 Java java教程 SpringBoot之整合Spring aop實例介紹

SpringBoot之整合Spring aop實例介紹

May 16, 2018 am 09:46 AM
spring springboot 介紹

本篇文章主要介紹了詳解SpringBoot之集成Spring AOP,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧

在開始之前,我們先把需要的jar包加入到工程裡。新增Maven依賴如下:

<dependency> 
  <groupId>org.springframework.boot</groupId> 
  <artifactId>spring-boot-starter-aop</artifactId> 
</dependency>
登入後複製

 接下來,我們進入正題。這裡的涉及的通知類型有:前置通知、後置最終通知、後置返回通知、後置異常通知、環繞通知,下面我們就具體的來看一下怎麼在SpringBoot中添加這些通知。

首先我們先建立一個Aspect切面類別:

@Component 
@Aspect 
public class WebControllerAop { 
 
}
登入後複製

指定切點:

//匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法 
@Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))") 
public void executeService(){ 
 
}
登入後複製

接著我們再建立一個Controller請求處理類別:

package com.zkn.learnspringboot.web.controller; 
 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
/** 
 * Created by zkn on 2016/11/19. 
 */ 
@RestController 
@RequestMapping("/aop") 
public class AopTestController { 
 
}
登入後複製

前置通知

設定前置通知:

/** 
 * 前置通知,方法调用前被调用 
 * @param joinPoint 
 */ 
@Before("executeService()") 
public void doBeforeAdvice(JoinPoint joinPoint){ 
  System.out.println("我是前置通知!!!"); 
  //获取目标方法的参数信息 
  Object[] obj = joinPoint.getArgs(); 
  //AOP代理类的信息 
  joinPoint.getThis(); 
  //代理的目标对象 
  joinPoint.getTarget(); 
  //用的最多 通知的签名 
  Signature signature = joinPoint.getSignature(); 
  //代理的是哪一个方法 
  System.out.println(signature.getName()); 
  //AOP代理类的名字 
  System.out.println(signature.getDeclaringTypeName()); 
  //AOP代理类的类(class)信息 
  signature.getDeclaringType(); 
  //获取RequestAttributes 
  RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 
  //从获取RequestAttributes中获取HttpServletRequest的信息 
  HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST); 
  //如果要获取Session信息的话,可以这样写: 
  //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION); 
  Enumeration<String> enumeration = request.getParameterNames(); 
  Map<String,String> parameterMap = Maps.newHashMap(); 
  while (enumeration.hasMoreElements()){ 
    String parameter = enumeration.nextElement(); 
    parameterMap.put(parameter,request.getParameter(parameter)); 
  } 
  String str = JSON.toJSONString(parameterMap); 
  if(obj.length > 0) { 
    System.out.println("请求的参数信息为:"+str); 
  } 
}
登入後複製

注意:這裡用到了JoinPoint和RequestContextHolder。透過JoinPoint可以獲得通知的簽章訊息,如目標方法名稱、目標方法參數資訊等。透過RequestContextHolder來取得請求資訊,Session資訊。

接下來我們在Controller類別中新增一個請求處理方法來測試前置通知:

@RequestMapping("/testBeforeService.do") 
public String testBeforeService(String key,String value){ 
 
  return "key="+key+" value="+value; 
}
登入後複製

前置通知攔截結果如下所示:

#後置回傳通知

配置後置回傳通知的程式碼如下:

/** 
 * 后置返回通知 
 * 这里需要注意的是: 
 *   如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息 
 *   如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数 
 * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值 
 * @param joinPoint 
 * @param keys 
 */ 
@AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys") 
public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){ 
 
  System.out.println("第一个后置返回通知的返回值:"+keys); 
} 
 
@AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys") 
public void doAfterReturningAdvice2(String keys){ 
 
  System.out.println("第二个后置返回通知的返回值:"+keys); 
}
登入後複製

Controller裡新增回應的請求處理資訊來測試後置回傳通知:

@RequestMapping("/testAfterReturning.do") 
public String testAfterReturning(String key){ 
 
  return "key=: "+key; 
} 
@RequestMapping("/testAfterReturning01.do") 
public Integer testAfterReturning01(Integer key){ 
 
  return key; 
}
登入後複製

當傳送請求為:http://localhost:8001/aop/testAfterReturning.do?key=testsss&value=855sss時,處理結果如圖所示:

當傳送請求為:http://localhost:8001/aop/testAfterReturning01.do?key=55553&value=855sss時,處理結果如圖所示:

後置例外通知

後置例外通知的設定方式如下:

/** 
 * 后置异常通知 
 * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法; 
 * throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行, 
 *   对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。 
 * @param joinPoint 
 * @param exception 
 */ 
@AfterThrowing(value = "executeService()",throwing = "exception") 
public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){ 
  //目标方法名: 
  System.out.println(joinPoint.getSignature().getName()); 
  if(exception instanceof NullPointerException){ 
    System.out.println("发生了空指针异常!!!!!"); 
  } 
}
登入後複製

Controller裡配置回應的請求處理類別:

@RequestMapping("/testAfterThrowing.do") 
public String testAfterThrowing(String key){ 
 
  throw new NullPointerException(); 
}
登入後複製

後置例外通知方法的處理結果如下所示:

後置最終通知

後置最終通知的配置方式如下:

/** 
 * 后置最终通知(目标方法只要执行完了就会执行后置通知方法) 
 * @param joinPoint 
 */ 
@After("executeService()") 
public void doAfterAdvice(JoinPoint joinPoint){ 
 
  System.out.println("后置通知执行了!!!!"); 
}
登入後複製

Controller類別配置對應的請求處理類別:

@RequestMapping("/testAfter.do") 
public String testAfter(String key){ 
 
  throw new NullPointerException(); 
} 
@RequestMapping("/testAfter02.do") 
public String testAfter02(String key){ 
 
  return key; 
}
登入後複製

當發送請求為:http:// localhost:8001/aop/testAfter.do?key=55553&value=855sss

當傳送請求為:http://localhost:8001/aop/testAfter02.do?key =55553&value=855sss

#環繞通知

## 環繞通知的設定方式如下:

/** 
 * 环绕通知: 
 *  环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。 
 *  环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型 
 */ 
@Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))") 
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){ 
  System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName()); 
  try { 
    Object obj = proceedingJoinPoint.proceed(); 
    return obj; 
  } catch (Throwable throwable) { 
    throwable.printStackTrace(); 
  } 
  return null; 
}
登入後複製

Controller對應的請求處理類別如下:

@RequestMapping("/testAroundService.do") 
public String testAroundService(String key){ 
 
  return "环绕通知:"+key; 
}
登入後複製

當發送請求為:http://localhost:8001/aop/testAroundService.do?key=55553

#當發送請求為:http://localhost:8001/aop/testAfter02.do?key=55553&value=855sss時,不符合環繞通知的切入規則,所以環繞通知不會執行。


完整的AOP配置程式碼如下:

package com.zkn.learnspringboot.aop; 
 
import com.alibaba.fastjson.JSON; 
import com.google.common.collect.Maps; 
import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.Signature; 
import org.aspectj.lang.annotation.*; 
import org.springframework.stereotype.Component; 
import org.springframework.web.context.request.RequestAttributes; 
import org.springframework.web.context.request.RequestContextHolder; 
 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpSession; 
import java.util.Enumeration; 
import java.util.Map; 
 
/** 
 * Created by zkn on 2016/11/18. 
 */ 
@Component 
@Aspect 
public class WebControllerAop { 
 
  //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法 
  @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))") 
  public void executeService(){ 
 
  } 
 
  /** 
   * 前置通知,方法调用前被调用 
   * @param joinPoint 
   */ 
  @Before("executeService()") 
  public void doBeforeAdvice(JoinPoint joinPoint){ 
    System.out.println("我是前置通知!!!"); 
    //获取目标方法的参数信息 
    Object[] obj = joinPoint.getArgs(); 
    //AOP代理类的信息 
    joinPoint.getThis(); 
    //代理的目标对象 
    joinPoint.getTarget(); 
    //用的最多 通知的签名 
    Signature signature = joinPoint.getSignature(); 
    //代理的是哪一个方法 
    System.out.println(signature.getName()); 
    //AOP代理类的名字 
    System.out.println(signature.getDeclaringTypeName()); 
    //AOP代理类的类(class)信息 
    signature.getDeclaringType(); 
    //获取RequestAttributes 
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 
    //从获取RequestAttributes中获取HttpServletRequest的信息 
    HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST); 
    //如果要获取Session信息的话,可以这样写: 
    //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION); 
    Enumeration<String> enumeration = request.getParameterNames(); 
    Map<String,String> parameterMap = Maps.newHashMap(); 
    while (enumeration.hasMoreElements()){ 
      String parameter = enumeration.nextElement(); 
      parameterMap.put(parameter,request.getParameter(parameter)); 
    } 
    String str = JSON.toJSONString(parameterMap); 
    if(obj.length > 0) { 
      System.out.println("请求的参数信息为:"+str); 
    } 
  } 
 
  /** 
   * 后置返回通知 
   * 这里需要注意的是: 
   *   如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息 
   *   如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数 
   * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值 
   * @param joinPoint 
   * @param keys 
   */ 
  @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys") 
  public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){ 
 
    System.out.println("第一个后置返回通知的返回值:"+keys); 
  } 
 
  @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys") 
  public void doAfterReturningAdvice2(String keys){ 
 
    System.out.println("第二个后置返回通知的返回值:"+keys); 
  } 
 
  /** 
   * 后置异常通知 
   * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法; 
   * throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行, 
   *   对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。 
   * @param joinPoint 
   * @param exception 
   */ 
  @AfterThrowing(value = "executeService()",throwing = "exception") 
  public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){ 
    //目标方法名: 
    System.out.println(joinPoint.getSignature().getName()); 
    if(exception instanceof NullPointerException){ 
      System.out.println("发生了空指针异常!!!!!"); 
    } 
  } 
 
  /** 
   * 后置最终通知(目标方法只要执行完了就会执行后置通知方法) 
   * @param joinPoint 
   */ 
  @After("executeService()") 
  public void doAfterAdvice(JoinPoint joinPoint){ 
 
    System.out.println("后置通知执行了!!!!"); 
  } 
 
  /** 
   * 环绕通知: 
   *  环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。 
   *  环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型 
   */ 
  @Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))") 
  public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){ 
    System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName()); 
    try {//obj之前可以写目标方法执行前的逻辑 
      Object obj = proceedingJoinPoint.proceed();//调用执行目标方法 
      return obj; 
    } catch (Throwable throwable) { 
      throwable.printStackTrace(); 
    } 
    return null; 
  } 
}
登入後複製

完整的Controller類別程式碼如下:

package com.zkn.learnspringboot.web.controller; 
 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
/** 
 * Created by zkn on 2016/11/19. 
 */ 
@RestController 
@RequestMapping("/aop") 
public class AopTestController { 
 
  @RequestMapping("/testBeforeService.do") 
  public String testBeforeService(String key,String value){ 
 
    return "key="+key+" value="+value; 
  } 
  @RequestMapping("/testAfterReturning.do") 
  public String testAfterReturning(String key){ 
 
    return "key=: "+key; 
  } 
  @RequestMapping("/testAfterReturning01.do") 
  public Integer testAfterReturning01(Integer key){ 
 
    return key; 
  } 
  @RequestMapping("/testAfterThrowing.do") 
  public String testAfterThrowing(String key){ 
 
    throw new NullPointerException(); 
  } 
  @RequestMapping("/testAfter.do") 
  public String testAfter(String key){ 
 
    throw new NullPointerException(); 
  } 
  @RequestMapping("/testAfter02.do") 
  public String testAfter02(String key){ 
 
    return key; 
  } 
  @RequestMapping("/testAroundService.do") 
  public String testAroundService(String key){ 
 
    return "环绕通知:"+key; 
  } 
}
登入後複製

以上是SpringBoot之整合Spring aop實例介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

wapi是什麼東西詳細介紹 wapi是什麼東西詳細介紹 Jan 07, 2024 pm 09:14 PM

wapi是什麼東西詳細介紹

編程新範式,當Spring Boot遇上OpenAI 編程新範式,當Spring Boot遇上OpenAI Feb 01, 2024 pm 09:18 PM

編程新範式,當Spring Boot遇上OpenAI

spring編程式事務有哪些實作方式 spring編程式事務有哪些實作方式 Jan 08, 2024 am 10:23 AM

spring編程式事務有哪些實作方式

利用Spring Boot以及Spring AI建構生成式人工智慧應用 利用Spring Boot以及Spring AI建構生成式人工智慧應用 Apr 28, 2024 am 11:46 AM

利用Spring Boot以及Spring AI建構生成式人工智慧應用

詳解win11能否運行PUBG遊戲 詳解win11能否運行PUBG遊戲 Jan 06, 2024 pm 07:17 PM

詳解win11能否運行PUBG遊戲

介紹最新的Win 11聲音調法方法 介紹最新的Win 11聲音調法方法 Jan 08, 2024 pm 06:41 PM

介紹最新的Win 11聲音調法方法

花亦山心之月鹿蜀技能屬性介紹 花亦山心之月鹿蜀技能屬性介紹 Mar 23, 2024 pm 05:30 PM

花亦山心之月鹿蜀技能屬性介紹

Spring如何設定事務隔離級別 Spring如何設定事務隔離級別 Jan 26, 2024 pm 05:38 PM

Spring如何設定事務隔離級別

See all articles