Springboot入门--进阶篇--AOP

什么是AOP?

AOP有什么用?

怎么运用AOP ?

相信是很多入门同学普遍存在的疑问,今天我就这些问题对AOP来一个通俗易懂的实操。首先AOP是一种编程思想,中文意思是 面向切面编程和面向对象编程(OOP)是一类。不过这里我不想讲干货,因为太无聊了,直接场景+实操,马上安排。

场景:

使用springboot框架开发的一个项目中,我们想记录用户每个接口请求log。具体log记录什么内容,这里简单设置,只记录请求时间和请求的接口名称。

实操:

1 )首先准备一个基于 Springboot框架的工程,不清楚的同学可以看我上一篇《Springboot入门》。

这里我创建一个工程名称为 lengfeng-03的工程,创建过程和工程目录如下:

2)创建一个简单接口

第一步、创建包,先在src下的主包“com.nc,lengfeng-03”下新增一个 名字为“controller”的包;

第二步、创建类,在“controller”中创建一个名为“MyController”的类;

第三步、添加注解,在类中类名字上方添加注解 @RestContoller ,这样这个类就是一个控制类了;

第四步、创建接口方法,在类中添加一个名字为"myApi01"的方法,返回类型随意,这里为String。

第五步、为接口添加请求标记,在方法上方添加

@RequestMapping(value = "/myapi",method = RequestMethod.GET)

其中"/myapi"为该接口的请求路径,请求方法为GET。

到这里,请求接口已经完成,完整代码如下:

package com.nc.lengfeng03.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
    @RequestMapping(value = "/myapi",method = RequestMethod.GET)
    public String myApi01()
    {
        return "OK";
    }
}

目录如下:

 

在浏览器中访问接口结果如下:

3)重点来了,创建一个Aspect类 “LogAspect”

第一步、添加AOP相关依赖,在pom.xml中添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

第二步、创建aspect包和创建LogAspect类。

package com.nc.lengfeng03.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(* com.nc.lengfeng03.controller.*.*(..))")
    /*
     第一个“*” 系 任意修饰词和 任意返回类型
     第二个“*” 系 该包下的任意类
     第三个“*” 系 该包所以类下的任意方法
     “(..)”  系 方法的任意参数
     */
    public void log(){

    }

    /*
     开始执行前需要处理的事情
     */
    @Before("log()")
    public  void before(JoinPoint joinPoint){
        System.out.println("------------Before Log----------------");
    }
    /*
        执行后需要处理的事情,无论执行成功与失败,相当于finally
        */
    @After(value="log()")
    public void afterExecution(JoinPoint joinPoint )
    {

        System.out.println("------------After Log----------------");
    }
    /*
        正常执行后需要处理的事情
        */
    @AfterReturning(value="log()")
    public void afterReturningExecution(JoinPoint joinPoint )
    {

        System.out.println("------------afterReturning Log----------------");
    }
    /*
        异常执行后需要处理的事情
        */
    @AfterThrowing(value="log()")
    public void afterThrowingExecution(JoinPoint joinPoint)
    {

        System.out.println("------------AfterThrowing Log----------------");
    }


    /*
   回环通知,贯穿整个执行过程
    */
    @Around(value = "log()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("------------before aroundAdvice Log----------------");
        // 在原始方法执行前执行的逻辑
        //doSomethingBefore();

        try {
            // 执行原始方法,并捕获返回值
            Object result = joinPoint.proceed();
            System.out.println("------------After aroundAdvice Log----------------");
            // 在原始方法执行后执行的逻辑
            // doSomethingAfter();

            // 返回原始方法的结果
            return result;
        } catch (Exception e) {
            // 在原始方法抛出异常时执行的逻辑
            System.out.println("------------Exception aroundAdvice Log----------------");
            //doSomethingOnException(e);
            throw e;
        } finally {
            // 最终的清理逻辑
            System.out.println("------------Finally aroundAdvice Log----------------");
            // doFinally();
        }
    }
}
/*
* 执行顺序
*------------before aroundAdvice Log----------------
------------Before Log----------------
------------afterReturning Log----------------
------------After Log----------------
------------After aroundAdvice Log----------------
------------Finally aroundAdvice Log----------------
*
* */

到这一个Aspect类创建完成了。

 重点看,这个切入点配置,意思是在 com.nc.lengfeng03.controller这个包下的所以类和所有方法均会被切入。具体解析如下

@Pointcut("execution(* com.nc.lengfeng03.controller.*.*(..))")

/* 第一个“*” 系 任意修饰词和 任意返回类型

第二个“*” 系 该包下的任意类

第三个“*” 系 该包所以类下的任意方法

“(..)” 系 方法的任意参数 */

4)测试结果

启动程序,在浏览器访问  "http://localhost:8080/myapi"

在Idea输出结果:

结果代表我请求 /myapi接口会执行 LogAAspect。

Before\After \Around的注解自行学习。具体也可以跟进代码注释和自己实操来学习。

5)记录Log

这个时候可以在LogAspect的 对应位置进行写log操作即可(可把log存文档或数据库,这里略)

结语

*AOP编程思想 简化了我们编程代码量:

如上述例子,原本需要再每个请求方法中都要添加写log代码的,现在执行声明一个 切入点(pointCut)就能实现。目标位置不需要任何代码。

*定义一个Acspect类两个注意点

 1、添加依赖 spring-boot-starter-aop ,aop的依赖有很多,请认准

 2、类上方添加@Aspect注解和@Component注解( Component注解会在项目启动时候把该类注册到spring容器中)

* 建议小白同学可以直接实操代码,从看到的结果中不断去解惑。不要一上来就看原理,看理论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值