您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關使用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進行集成有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。