SpringBoot AOP 超简单实现超详细讲解

我们都知道Spring的核心IOC和AOP,今天说的就是经常接触的AOP。
AOP,面向切面编程,百度一下都知道,但是没啥luan用,啥是切面?啥叫面向切面编程?怎么使用都不知道,那你还说你知道AOP?
不过不知道不要紧,看完我的文章就懂了。我会用很简洁的语言来描述这个东西,并且加上简单的代码实现辅助理解。

我们首先想象这么一个场景,我做一个网页,Controller里面有10个接口需要用户登录才能请求,怎么实现?

1.普通人的做法:就是在10个接口里面分别取到用户信息,然后判断用户是否登录,否则直接返回或者抛异常等等,代码很多,很低级。
2.聪明人的做法:我们把校验用户的代码封装成一个方法,或者一个Util,然后在controller里面再调用方法校验,有一点那个味了,但是还是麻烦。
3.大佬的做法:采用AOP。
我们知道,懒惰才是人们科技进步的第一动力,AOP符合我们懒惰的情况下,还能够将我们的业务和校验(不光是校验)拆分开来,两者互不影响,简化我们的业务代码。

SpringBoot实现AOP,我从自定义注解开始说起。我们知道SpringBoot有很多注解,这很方便我们的开发,那么怎么自定义一个注解呢,很简单,加一个@interface就好了。
(1)我们首先创建一个AnnotationTest的注解

@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
    String value() default "";

    String type() default "1";
}

@Target注解,表示你这个注解标注在哪里,我这里用的ElementType.METHOD,表示我是标注在方法上的,加在类上就会报错,其他的自行百度。
@Retention(RetentionPolicy.RUNTIME),注解的生命周期,RetentionPolicy.RUNTIME表示的是在程序运行时。
我还写了两个属性,一个value和type,指定默认值,这个是我们在打注解的时候传参用的。
(2)来试试我们的注解呢,新建一个Controller,将我们的注解打在接口上。
并且将type改成2,在这个方法里,我往Redis里面插入了一条数据,然后从数据库查询了用户的记录再返回。

@RestController
@RequestMapping("/test")
public class UserInfoController{
    @Resource
    UserInfoService userInfoService;

    @RequestMapping(value = "/testOne")
    @AnnotationTest(type = "2")
    public ResultMsg test(){
        Double aDouble = RedisCacheUtil.inst().zincrementScore("TEST", 1, "test");
        System.out.println(aDouble);
        List<UserInfo> list = userInfoService.list();
        return ResultMsg.success(list);
    }
}

(3)我们光定义了注解和加上注解是没有用的,关键的是我们切面里面作什么处理。接下来一步是关键,我们新建一个TestAopAnnoAspect的类,注意两个很关键的注解@Aspect和@Component,@Aspect表示该类是一个切面,@Component就不说了嘛。

@Aspect
@Component
public class TestAopAnnoAspect {

    @Pointcut("execution(* com.example.demo.controller..*(..))")
    public void PointCut(){
    }
    
    @Before("execution(* com.example.demo.controller..*(..))")
    public void Before() {
        System.out.println("请求之前");
    }

    @Around("execution(* com.example.demo.controller..*(..))")
    public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕");
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AnnotationTest annotationTest = method.getAnnotation(AnnotationTest.class);
        String type = annotationTest.type();
        System.out.println("type 为:" + type);
        return joinPoint.proceed();
    }

    @After("execution(* com.example.demo.controller..*(..))")
    public void After() {
        System.out.println("在请求之后");
    }

    @AfterReturning("execution(* com.example.demo.controller..*(..))")
    public void AfterReturning() {
        System.out.println("在返回之后");
    }
}

说明:在切面里,我们可以作几种处理,通过注解,常用的我已经列出来了,
@PointCut:切点,不能有方法体。
@Before:程序执行之前
@After:程序执行之后
@Around:环绕整个程序执行
@AfterReturning:返回之前
这些注解的作用,我做一个比喻,比如我们程序的执行是一根筷子,从筷子头到筷子尾。那么这些注解就表示了,我们要在这根筷子的什么部位做什么事情。
最最最最最最重要的:注解里面execution表达式怎么写?下面简单列了一下结构

    /**
     * execution:表达式主体
     * 第一部分  代表方法返回值类型 *表示任何类型
     * 第二部分  com.example.demo.controller 表示要监控的包名
     * 第三部分 .. 代表当前包名以及子包下的所有方法和类
     * 第四部分 * 代表类名,*代表所有的类
     * 第五部分 *(..) *代表类中的所有方法(..)代表方法里的任何参数
     */

然后我们在浏览器请求一下数据看看效果:
在这里插入图片描述
再看看控制台的打印:
在这里插入图片描述
通过打印我们可以知道什么呢?
1.AOP几个注解的执行顺序,注意第四行打印5.0,这是我们controller给Redis增加值改变的。
2.我们定义的注解里面type属性,默认是1的,但是我们Controller使用的时候设置type为2,这里也相应修改了。

上面就是AOP的一个简单示例了,很简单,但是也是五脏俱全。示例业务比这个复杂但也还好,简单举个例子,上面@Around注解里面有一个参数是ProceedingJoinPoint joinPoint,ProceedingJoinPoint里面又携带了很多信息。
比如:
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();//拿到方法
Object[] allArgs = joinPoint.getArgs();//拿到参数
CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature();//连接点捕获的代码块.它可以是方法,构造函数,初始化程序(静态或非静态)或建议
String[] parameterNames = codeSignature.getParameterNames();//拿到参数
如果你有收获别忘了点赞哦,有不对的地方欢迎指出。

  • 15
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值