This article mainly introduces the detailed explanation of SpringBoot's integration of Spring AOP. The editor thinks it is quite good, so I will share it with you now and give it as a reference. Let’s follow the editor and take a look.
Before we start, we first add the required jar packages to the project. The new Maven dependencies are as follows:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
Next, we get to the point. The notification types involved here are: pre-notification, post-final notification, post-return notification, post-exception notification, and wrap-around notification. Let's take a detailed look at how to add these notifications in SpringBoot.
First we create an Aspect aspect class:
@Component @Aspect public class WebControllerAop { }
Specify the pointcut point:
//匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法 @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))") public void executeService(){ }
Then we create a Controller request processing class:
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 { }
Pre-notification
Configure pre-notification:
/** * 前置通知,方法调用前被调用 * @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); } }
Note: JoinPoint and RequestContextHolder are used here. The signature information of the notification can be obtained through JoinPoint, such as the target method name, target method parameter information, etc. Obtain request information and Session information through RequestContextHolder.
Next we add a request processing method in the Controller class to test the pre-notification:
@RequestMapping("/testBeforeService.do") public String testBeforeService(String key,String value){ return "key="+key+" value="+value; }
The pre-notification interception result is as follows:
Post-return notification
The code for configuring post-return notification is as follows:
/** * 后置返回通知 * 这里需要注意的是: * 如果参数中的第一个参数为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); }
Add response request in Controller Process the information to test the post-return notification:
@RequestMapping("/testAfterReturning.do") public String testAfterReturning(String key){ return "key=: "+key; } @RequestMapping("/testAfterReturning01.do") public Integer testAfterReturning01(Integer key){ return key; }
When the request is sent: http://localhost:8001/aop/testAfterReturning.do?key=testsss&value=855sss, the processing result is as shown in the figure:
When the request is sent to: http://localhost:8001/aop/testAfterReturning01.do?key=55553&value=855sss, the processing result is as shown in the figure:
Post exception notification
The configuration method of post exception notification is as follows:
/** * 后置异常通知 * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法; * 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("发生了空指针异常!!!!!"); } }
Configuration in Controller Response request processing class:
@RequestMapping("/testAfterThrowing.do") public String testAfterThrowing(String key){ throw new NullPointerException(); }
The processing results of the post-exception notification method are as follows:
Post-final notification
The post-final notification is configured as follows:
/** * 后置最终通知(目标方法只要执行完了就会执行后置通知方法) * @param joinPoint */ @After("executeService()") public void doAfterAdvice(JoinPoint joinPoint){ System.out.println("后置通知执行了!!!!"); }
Controller class configures the corresponding request processing class:
@RequestMapping("/testAfter.do") public String testAfter(String key){ throw new NullPointerException(); } @RequestMapping("/testAfter02.do") public String testAfter02(String key){ return key; }
When the request is sent: http:// localhost:8001/aop/testAfter.do?key=55553&value=855sss
When sending the request: http://localhost:8001/aop/testAfter02.do?key =55553&value=855sss
Surround notification
Surround notification is configured as follows:
/** * 环绕通知: * 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。 * 环绕通知第一个参数必须是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; }
The request processing class corresponding to the Controller is as follows:
@RequestMapping("/testAroundService.do") public String testAroundService(String key){ return "环绕通知:"+key; }
When the request is sent: http://localhost:8001/aop/testAroundService.do?key=55553
When the request is sent to: http://localhost:8001/aop/testAfter02.do?key=55553&value=855sss, it does not comply with the cut-in rules of the surrounding notification, so the surrounding notification will not be executed.
The complete AOP configuration code is as follows:
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; } }
The complete Controller class code is as follows:
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; } }
The above is the detailed content of SpringBoot integrated Spring aop example introduction. For more information, please follow other related articles on the PHP Chinese website!