8、SpringBoot中的Aop定义及处理

Aop:全称为Aspect Oriented Programming(面向切面编程),在实际业务场景中,我们可以通过Aop进行一些业务处理前中后以及异常情况下的一些处理。

一、SpringBoot中使用Aop首先要添加aop的依赖包:

<!-- 面向切面变成AOP相关依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

二、定义一个Aop的处理类

  • 添加注解@Aspect注解,表示这是一个AOP的切面类,然后添加@Component 表示将这个类交给Spring容器进行管理,然后再定义一个或多个切入点,通常在@Before,@After,@AfterReturning,@AfterThrowing等注解上使用上述定义好的切入点来进行相应的业务处理,比如权限校验,数据统计,日志打印等业务。在定义切入点的时候可以是直接指定一个包,或是这个包中的某个类或是某个方法进行切入,也可以是指定一个注解作为切入点,二者分别使用execution表达式和annotation()进行标注:
@Aspect
@Component
public class AopTestHandler {
    private static Logger log = LoggerFactory.getLogger(AopTestHandler.class);
    @Pointcut("execution(* com.example.controller..AopController.aopTest2(..))")
    public void pointCut(){}
    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void pointCut1(){}
    @Pointcut("execution(* com.example.controller..AopController.aopTest3(..))")
    public void pointCut2(){}


    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint){
        log.info("进入到AopTestHandler中的doBefore方法中");
        Signature signature = joinPoint.getSignature();
        log.info("===={}==={}==={}==={}==={}",signature.getDeclaringType(),
                signature.getDeclaringTypeName(),
                signature.getModifiers(),
                signature.getName(),
                signature.getClass());
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest();
        String methodName = httpServletRequest.getMethod();
        String url = httpServletRequest.getRequestURL().toString();
        String ip = httpServletRequest.getRemoteAddr();
        log.info("获取请求中的方法:{},url:{},ip:{}",methodName,url,ip);
    }
    @After("pointCut()")
    public void affter(){
        log.info("进入到AopTestHandler中的affter方法中");

    }

    @AfterReturning("pointCut()")
    public void affterReturning(){
        log.info("进入到AopTestHandler中的affterReturning方法中");

    }

    @AfterThrowing(pointcut = "pointCut()",throwing = "ex")
    public void affterThrowing(JoinPoint joinPoint,Throwable ex){
        log.info("进入到AopTestHandler中的affterThrowing方法中");
    }



    @Before("pointCut1()")
    public void Before(){
        log.info("进入到AopTestHandler中的Before方法中测试Annotation类型");
    }

    @Around("pointCut2()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("进入到AopTestHandler中的around方法中测试@Around注解");
        log.info("AopTestHandler中获取方法名:{}",proceedingJoinPoint.getSignature().getName());
        Object obj = proceedingJoinPoint.proceed();
        log.info("方法执行结束之后的AopTestHandler中");
        return obj;
    }


}

注解解释:

1、@Aspect:表示这个类是一个切面类

2、@Pointcut(...):表示这是一个切入点,里面有两种定义方式:execution(* com.example.controller..AopController.aopTest1(..))指定某个包下面的某些类中的某些方法进行切入,第一个“*”表示返回类型,“com.example.controller”表示包名,“..”表示这个包下的所有包及子包,“AopController”表示这个类,也可以将它换成“*”表示所有类,“*(..)”表示这个类下的所有方法,“..”表示任何参数的方法。annotation()用于标示某个注解做为切入点,可以是自定义注解,上述案例中以GetMapping注解做为切入点。

3、@Before():表示在这个切入点之前执行的一些处理。

4、@After():表示在切入点执行之后进行的一些处理。

5、@AfterReturning():表示在切入点进行返回数据的时候进行的一些处理。

6、@AfterThrowing():标示在切入点抛出异常之后进行的一些处理。

7、@Around():环绕增强型,在执行目标方法前和目标方法之后都会进行执行。

参数解释:

1、JoinPoint:可以通过JoinPoint对象获取一个Signature,通过Signature获取调用的类名,方法名,等信息。

 

三、自定义一个Controller类进行aop测试:

  • aopTest1用来测试execution()表达式,appTest2用来测试annotation()表达式
​
@RestController
@Api(value="AopTest")
public class AopController {
    private static Logger log = LoggerFactory.getLogger(AopController.class);
    @RequestMapping("/aopTest1/{param}"",method = RequestMethod.GET)
    @ApiOperation(value="execution测试")
    public JsonResult aopTest1(@PathVariable @ApiParam(value = "param") String param){
        log.info("进入到AopController中的aopTest1方法中");
        log.info("获取到的参数为:{}",param);
//        try{
//            int i = 1/0;
//        }catch (Exception e){
//            throw new BusinessException(BusinessExceptionEnum.BUSINESS_EXCEPTION);
//        }
        return new JsonResult();
    }

    @PostMapping(value ="aopTest2")
    @ApiOperation(value="annotation测试")
    public JsonResult aopTest2(@RequestParam @ApiParam(value = "param1") String param1, @RequestParam @ApiParam(value="param2") String param2){
        log.info("获取到参数:{}--{}",param1,param2);
        return new JsonResult("0","annotation测试");
    }



    @RequestMapping(value = "/aopTest3",method = RequestMethod.GET)
    @ApiOperation("测试@Around注解")
    public JsonResult aopTest3(){
        log.info("进入到AopController中的aopTest3方法中");
        return new JsonResult();
    }


}


​

四、测试AOP

启动springboot工程,用swagger进行测试上述定义好的方法,并且在控制台可以看出上述方法的执行顺序:

1、测试execution()表达式

 

 

控制台打印信息:从打印信息可以看出AOP中各个注解对应的方法的执行顺序:Before -> controller方法 -> AfterReturning -> After

 

2、annotation表达式测试:

 

控制台打印信息:因为只是annotation表达式,各个注解的执行顺序在上述execution表达式测试中已经体现,现在不再赘述。

 

3、@Around注解测试

 

控制台信息打印:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值