Spring AOP

AOP:面向切面编程,是一种思想,简单理解就是:针对于某一类通用的事情集中处理

SpringAOP:SpringAop是一个框架,提供了一种对 AOP思想的实现,它们的关系类似IoC和DI

AOP的常见使用

统一的用户登录判断,统一日志记录,统一方法执行时间统计,统一的返回格式设置,统一的异常处理,事务的开启和提交

AOP相关概念

1.切面(类):某一方面的具体内容就是一个切面,比如用户的登录判断就是一个切面,日志的统计记录也是一个切面

2.切点(方法):定义一个拦截规则

3.通知(方法具体实现代码):执行 AOP 逻辑任务

  3.1前置通知: 在目标方法(实际要执行的方法) 调用之前执行的通知
  3.2后置通知: 在目标方法调用之后执行的通知
  3.3环绕通知: 在目标方法调用前后都执行的通知(例如方法执行时间的统计)
  3.4异常通知: 在目标方法抛出异常时执行的通知
  3.5返回通知: 在目标方法返回时执行的通知

4.连接点:所有有可能触发切点的事件

SpringAOC的使用

1.添加Spring AOP 框架

Spring AOP_第1张图片

Spring AOP_第2张图片

因为我们使用的是springboot项目,所以用的也是基于springboot的AOP框架

2.创建切面

在与启动类同级或者子集中创建一个类(切面),给这个类添加@Aspect注解和一个类注解可以是Component,也可以是Service等

@Aspect // 切面
@Component
public class UserAOP {
}

3.创建切点(定义拦截规则)

@Aspect // 切面
@Component
public class UserAOP {
    // 切点
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut(){}
}

execution() 意思是执行execution括号里面的代码.  *代表的是返回值,这里*号代表所有的返回值.com.example.demo.controller.UserController是包名+类名,意思是在demo底下的controller底下的UserController,所有返回值为*(所有的方法)都进行拦截. UserController后面的*表示具体拦截哪个方法(这里是*号所以表示任意)括号里的点点表示参数为任意
excution(<修饰符><返回类型><包.类.方法(参数)><异常>)

4.创建通知

@Aspect // 切面
@Component
public class UserAOP {
    // 切点
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut(){}
    // 前置通知
    @Before("pointcut")
    public void doBefore(){
        System.out.println("执行了前置通知: "+ LocalDateTime.now());
    }
}

5.创建连接点

controller底下的UserController类

package com.example.demo.controller;

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

@RestController
public class UserController {
    @RequestMapping("/user/sayHi")
    public String sayHI(){
        System.out.println("执行了sayHi方法");
        return "hi springboot aop";
    }
    @RequestMapping("/user/login")
    public String login(){
        System.out.println("执行了login方法");
        return "do user login";
    }
}

controller底下的ArticleController类

@RestController
public class ArticleController {
    @RequestMapping("/article/sayHi")
    public String sayHI(){
        System.out.println("执行了article sayHi方法");
        return "hi article springboot aop";
    }
}

依次在浏览器访问这三个方法

Spring AOP_第3张图片

 可以看到UserController类中的sayHi方法和login方法都执行了前置通知,而ArticleController类里面的sayHi方法没有执行前置通知,这是因为我们在创建切点,定义拦截规则的时候规定了的.

环绕通知

  // 环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("开始执行环绕通知 ");
        Object obj = joinPoint.proceed();
        System.out.println("结束执行环绕通知");
        return obj;
    }

环绕通知需要把事件(正在执行的连接点)本身传递给环绕通知方法(ProceedingJoinPoint),然后在合适的位置调用ProceedingJoinPoint的proceed方法.最后再把执行的结果返回给框架

Spring AOP_第4张图片

 Spring AOP实现原理

Spring AOP_第5张图片

 Spring AOP底层实现:1.JDK 动态代理(通过反射实现,要求被代理的类一定要实现接口),性能较高
2.CGLIB(通过生成代理类的子类实现动态代理,要求被代理类不能被final修饰)

你可能感兴趣的:(spring,java,后端)