1. 什么是AOP?
AOP(Aspect Oriented Programming):面向切面编程。
面向切面编程是一种思想,其实就是对某一类事情进行统一的处理。而 SpringAOP就是一种AOP的具体实现的框架。这就好比 IOC 和 DI 一样的关系。
上述就是对登录功能进行了一个统一的处理!
2. AOP能用来干些什么?
除了上面的判断登录之外,还有:
- 统一日志记录
- 统一的方法执行时间统计
- 统一的返回格式设置
- 统一的异常处理
- 事务的开启和提交
3. 学习AOP
3.1 AOP的组成
3.1.1 切面(Aspect)
切面:定义的是事件,也就是AOP是用来做啥的。
例如:用来做用户登录校验
3.1.2 切点(Pointcut)
切点:定义具体拦截规则。
例如:哪些接口需要判断用户登录,哪些不需要
3.1.3 通知(Advice)
通知:定义AOP具体的执行方法。
例如:从 Session 中获取用户信息,如果获取到则是登录,没获取到表示未登录。
3.1.4 连接点(Jion Point)
连接点:有可能触发切点的所有点,也就是所有接口。
3.2 SpringAOP实现
3.2.1 添加依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
3.2.2 定义切面
@Aspect// 表示这个为切面@ComponentpublicclassUserAspect{}
上述中,@Aspect注解表示这个类为切面类。@Component表示这个类随着SpringBoot启动而启动。
3.2.3 定义切点
@Aspect// 表示这个为切面@ComponentpublicclassUserAspect{// 定义切点@Pointcut("execution(* com.example.springaop.controller.UserController.*(..))")publicvoidpointcut(){}}
使用@Pointcut注解进行定义切点,格式为 :
excution(<修饰符><返回类型><包.类.⽅法(参数)><异常>) ,一般修饰符和异常可省略。
3.2.4 执行通知
@Aspect// 表示这个为切面@ComponentpublicclassUserAspect{// 定义切点@Pointcut("execution(* com.example.springaop.controller.UserController.*(..))")publicvoidpointcut(){}// 前置通知@Before("pointcut()")publicvoiddoBefore(){System.out.println("执行了前置通知");}// 后置通知@After("pointcut()")publicvoiddoAfter(){System.out.println("执行了后置通知");}// 返回之后通知@AfterReturning(value ="pointcut()",returning ="")publicvoiddoAfterReturning(){System.out.println("执行了返回之后通知");}// 异常通知@AfterThrowing("pointcut()")publicvoiddoAfterThrowing(){System.out.println("执行了异常通知");}// 环绕通知@Around("pointcut()")publicObjectdoAroud(ProceedingJoinPoint joinPoint){Object result =null;System.out.println("环绕通知执行之前");try{// 执行目标方法
result = joinPoint.proceed();}catch(Throwable e){thrownewRuntimeException(e);}System.out.println("环绕通知执行之后");return result;}}
可以通过下面看到执行顺序:
4. SpringAOP实现原理
SpringAOP是构建在动态代理的基础上实现的,因此 Spring 对 AOP 支持局限于方法级别上。
- JDK Proxy:默认情况下,实现了接口的类,使用 AOP 基于 JDK 生成代理类
- CGLIB:默认情况下,没有实现接口的类,通过实现代理类的子类来实现动态代理(被final修饰的类不能代理)
- 两者底层都是通过反射
JDK 和 CGLIB 区别:
- JDK来自JAVA;CGLIB属于三方
- JDK:是通过实现类接口的类来生成代理类;CGLIB是通过实现了代理类的子类来实现动态地理
- JDK7之后版本,JDK Proxy性能高于 CGLIB;JDK7之前,CGLIB 性能远远高于 JDK Proxy
版权归原作者 一个想打拳的程序员 所有, 如有侵权,请联系我们删除。