Spring基础 SpringAOP

前言

我们都知道Spring中最经典的两个功能就是IOC和AOP

我们之前也谈过SpringIOC的思想 容器编程思想了

今天我们来谈谈SpringAOP的思想

首先AOP被称之为面向切面编程

实际上面向切面编程是面向对象的编程的补充和完善

重点就是对某一类问题的集中处理

前面我们写的统一异常管理和统一结果返回以及拦截器都是基于这个思想来创建的

我们发现这里的共性就是这些操作都有一个特点,他们都是统一操作的接口...

但是拦截器作用的是接口,AOP这类提供的操作的是方法

概念

切点(Printcut):这里的切点可以理解为切入的点,这里指的是一组规则,告诉程序对哪些方法来进行增强

连接点(Join Point):指的是满足上述切点规则的方法

通知(Advice): 对方法在前面/后面/周围加上一些处理(共性功能)

切面(Aspect): 切点 + 通知  (一类问题的解决方案)

SpringAOP

Spring 提供了一个通用的接口,可以帮助我们实现AOP的功能

比如对应用程序的监控,我们可以对每个接口之间加上计算实际运行时间

从计算的瓶颈解决问题

我们可以记录开始时间和节数时间然后作差,但是如果每个接口都一个一个写就没意思了

如果这里调用链非常长,我们还需要一个一个写,就太难受了呀

于是我们来使用AOP来解决问题

这里我们要先导入aop的依赖

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

这里虽然文件是Aspect包中的,但是却是Spring实现的

简单的实现

@Aspect
@Component
@Slf4j
public class TimeRecordAspect {@Around("execution(* com.example.bookmanager.controller.*.*(..))")public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {//记录开始时间long startTime = System.currentTimeMillis();//目标方法Object proceed = joinPoint.proceed();//结束时间long endTime = System.currentTimeMillis();//打印日志log.info("方法执行时间"+(endTime-startTime)+"ms");return proceed;}
}

这样我们就可以在调用接口的时候打印其执行的时间了

以上的@Around注解表示就是环绕

在目标函数执行的前后都会执行

通知类型有如下几种

@Around: 环绕通知, 此注解标注的通知⽅法在⽬标⽅法前, 后都被执⾏
@Before: 前置通知, 此注解标注的通知⽅法在⽬标⽅法前被执⾏
@After: 后置通知, 此注解标注的通知⽅法在⽬标⽅法后被执⾏, ⽆论是否有异常都会执⾏
@AfterReturning: 返回后通知, 此注解标注的通知⽅法在⽬标⽅法后被执⾏, 有异常不会执⾏
@AfterThrowing: 异常后通知, 此注解标注的通知⽅法发⽣异常后执⾏
1.切点:这里的规则就是上面的Around里面的切点表达式
2.与切点表达式匹配的都是他描述的方法,也称之为连接点
3.通知 目标方法前后要做的操作
那么多包两层会怎么样呢????
比如先使用@Around再使用@Before和@After.....
这里就像一个栈一样,先进后出
注意:Around一定是要有返回值的,因为其有目标方法的执行
        Around的优先级高于其他

接口正常时

接口异常时

我们发现before和after在接口正常和异常的情况下都是会执行的

切点

注意需要一个空参方法
我们可以使用@Pointcut注解来代替大量重复的注解,后面的切点表达式就可以实现复用了
注意,如果切点是private的,在其他的类还是不能使用,声明为public并且使用全限定名即可
注:默认执行顺序为字典序,不可取,我们可以使用一个@Order来改变其优先级
数字越大优先级越低
下面我们来介绍一下切点表达式的内容
execution(* com.example.bookmanager.controller.*.*(..))
execution + 访问修饰符(可省略) + 返回类型 + 全类名 + 参数 + 异常(可省略)
这里的*表示任意单词可以替换返回类型,包名,类名方法等
..表示匹配多个任意符号
假设我们想对不同的类中的不同的方法来执行对应的连接
这个时候使用切点表达式就不能很好的完成问题了 我们就需要使用自定义注解对需要进行通知的方法进行修饰了

自定义注解

首先我们需要创建一个注解

我们需要声明他的作用域和生命周期

然后我们需要去做他的配置类/实现类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyAspect {}

我们暂时只实现一个Around功能

这里的@annotation就表示对什么注解生效

@Aspect
@Component
@Slf4j
public class MyAspectDemo {@Around("@annotation(com.example.springaop.config.MyAspect)")public Object doAround(ProceedingJoinPoint joinPoint) {log.info("do around before");Object o = null;try {o = joinPoint.proceed();} catch (Throwable e) {throw new RuntimeException(e);}log.info("do around after");return  o;}
}

后面我们可以用@MyAspect注解来修饰对应的方法

这样在调用的时候就可以实现其Around功能

SpringAOP的实现方式??

1.使用Aspect注解来实现

2.使用自定义注解来实现

3.基于XML文件使用api来实现  config:aop

4.基于代理来实现(比较久远)

代理模式(重点)

定义:

为其他对象提供⼀种代理以控制对这个对象的访问. 它的作⽤就是通过提供⼀个代理类, 让我们在调⽤⽬标⽅法的时候, 不再是直接对⽬标⽅法进⾏调⽤, ⽽是通过代理类间接调⽤.
代理前
代理后
生活中的代理也有很多
比如中介,经纪人,经销商,秘书........
主要角色:
Subject:业务接口类
RealSubject:业务实现类 具体的业务执行,也可以是被代理对象
Proxy:代理类,为RealSubject的代理
适用场景:
1.无法直接调用目标对象
2.目标对象给我们提供的功能不够,我们希望对目标对象已提供的方法进行功能增强
代理模式分为静态代理和动态代理
我们以生活中的中介来举例
静态代理就是我选好想看的房源之后,房源已经绑定了对应的中介了
动态代理就是我们选好想看的房源之后,平台自动分配中介
这种提前分配就称之为静态代理
运行时分配的就是动态代理

静态代理代码实现

接口
public interface Subject {void rentHouse();
}

房东

public class RealHouseSubject implements  Subject{@Overridepublic void rentHouse() {System.out.println("我要卖房子");}
}

中介

public class HouseProxy implements  Subject{private RealHouseSubject target;public HouseProxy(RealHouseSubject target) {this.target = target;}@Overridepublic void rentHouse() {System.out.println("开始代理");target.rentHouse();System.out.println("结束代理");}
}

类似于适配器模式,这里也是持有了第三方的房东授权

缺点是代码都写死了

动态代理实现

//JDK代理
public class JDKInvocationHandler implements InvocationHandler {private RealHouseSubject target;public JDKInvocationHandler(RealHouseSubject target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("开始代理");Object o = method.invoke(target, args);System.out.println("结束代理");return o;}
}//main方法RealHouseSubject subject = new RealHouseSubject();Subject proxy= (Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(),new Class[]{Subject.class},new JDKInvocationHandler(subject));proxy.rentHouse();

这里有两种  CGLib和 JDK动态代理

这里就不做要求了

注意代理是基于反射实现的

主要记得这里的两个区别

JDK可以代理接口 不能代理类

CGLib可以代理接口也可以代理类

但是性能我不太确认,网上说两个性能谁高的都有,可能有硬件的影响  

博主可以后面测测看

注意Spring和SpringBoot在这里AOP的实现也是有差异的

代理工厂中有一个参数 proxyTargetClass  

默认Spring是false   默认实现接口使用JDK代理

SpringBoot从2.x之后设置为true     默认全部使用CGLib实现代理

proxyTargetClass⽬标对象代理⽅式
false实现了接⼝jdk代理
false未实现接⼝(只有实现类)cglib代理
true实现了接⼝cglib代理
true未实现接⼝(只有实现类)cglib代理

小总结

 AOP是⼀种思想,是对某⼀类事情的集中处理.Spring框架实现了AOP,称之为SpringAOP
2. SpringAOP常⻅实现⽅式有两种:

1.基于注解@Aspect来实现

2.基于⾃定义注解来实现,还有⼀些更原始的⽅式,⽐如基于代理,基于xml配置的⽅式,但⽬标⽐较少⻅
3. SpringAOP是基于动态代理实现的,有两种⽅式:

1.基本JDK动态代理实现

2.基于CGLIB动态代理
实现.运⾏时使⽤哪种⽅式与项⽬配置和代理的对象有关

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/640694.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hadoop安装记录

零、版本说明 centos [rootnode1 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)jdk [rootnode1 ~]# java -version java version "1.8.0_311" Java(TM) SE Runtime Environment (build 1.8.0_311-b11) Java HotSpot(TM) 64-Bit Server VM (…

HarmonyOS ArkUI实战开发-手势密码(PatternLock)

ArkUI开发框架提供了图案密码锁 PatternLock 组件&#xff0c;它以宫格图案的方式输入密码&#xff0c;用于密码验证&#xff0c;本节读者简单介绍一下该控件的使用。 PatternLock定义介绍 interface PatternLockInterface {(controller?: PatternLockController): PatternL…

Hadoop3:HDFS、YARN、MapReduce三部分的架构概述及三者间关系(Hadoop入门必须记住的内容)

一、HDFS架构概述 Hadoop Distributed File System&#xff0c;简称HDFS&#xff0c;是一个分布式文件系统。 1&#xff09;NameNode(nn)&#xff1a;存储文件的元数据&#xff0c;如文件名&#xff0c;文件目录结构&#xff0c;文件属性&#xff08;生成时间、副本数、文件…

探索数学语言模型的前沿进展——人工智能在数学教育和研究中的应用

数学一直被认为是科学的基石&#xff0c;对于推动技术进步和解决现实世界问题具有重要意义。然而&#xff0c;传统的数学问题解决方式正面临着数字化转型的挑战。MLMs的出现&#xff0c;预示着数学学习和研究方式的一次革命。 MLMs&#xff0c;包括预训练语言模型&#xff08;…

RoadBEV:鸟瞰视图下的路面重建

作者&#xff1a;Tong Zhao&#xff0c;Lei Yang&#xff0c;Yichen Xie等 编译&#xff1a;董亚微一点人工一点智能 RoadBEV&#xff1a;鸟瞰视图下的路面重建https://mp.weixin.qq.com/s/hDNHwvpFe39doiXlVc-d7Q 摘要&#xff1a;道路的路面状况&#xff0c;特别是几何轮廓…

在誉天学习云计算HCIE,担心考试考不过?

誉天定制化课程内容覆盖了所有考试重点&#xff0c;可以系统地掌握理论与实践知识。 对于笔试&#xff0c;类似于备考驾照理论学习阶段&#xff0c;誉天为大家提供在线模拟测试系统&#xff0c;帮助大家掌握云计算笔试考点。笔试通过后&#xff0c;18个月内&#xff08;一年半…

Mysql基础(二)数据类型和约束

一 数据类型 讲解主要的数据类型,不面面俱到,后续遇到具体问题再查询补充扩展&#xff1a; 知识点的深度和广度以工作为导向 ① int float M : 表示显示宽度&#xff0c;M的取值范围是(0, 255)例如: int(5),当数据宽度小于5位的时候在数字前面需要用字符填满宽度说明&…

html显示PDF并兼容IE浏览器的解决方案

方案一、vue-pdf插件 缺点&#xff1a;IE11显示空白&#xff0c;编译后的Edge测试环境可以正常线上&#xff0c;打到线上报错&#xff0c;谷歌和百分浏览器显示完美 1、vue 只显示核心代码&#xff0c;需要安装vue-pdf插件 <vue-pdf :src"ivcPdfUrl"></v…

Vitis HLS 学习笔记--优化指令-ARRAY_PARTITION

目录 1. ARRAY_PARTITION 概述 2. 语法解析 2.1 参数解释 2.1.1 variable 2.1.2 type 2.1.3 factor 2.1.4 dim 2.2 典型示例 2.2.1 dim1 2.2.2 dim2 2.2.3 dim0 3. 实例演示 4. 总结 1. ARRAY_PARTITION 概述 ARRAY_PARTITION 指令中非常重要&#xff0c;它用于优…

使用 OpenCV 测量物体尺寸

使用 OpenCV 测量物体尺寸 你是否曾经遇到过这样的问题&#xff1a;想要知道计算器的精确尺寸&#xff0c;但手头又没有专业的测量工具&#xff1f;别担心&#xff0c;今天我们就来教大家一个简单又实用的方法&#xff0c;通过一张A4纸就能估算出计算器的宽度和高度&#xff0c…

了解边缘计算,在制造行业使用边缘计算。

边缘计算是一种工业元宇宙技术&#xff0c;可以帮助组织实现其数据的全部潜力。 处理公司的所有数据可能具有挑战性&#xff0c;而边缘计算可以帮助公司更快地处理数据。在制造业中&#xff0c;边缘计算可以帮助进行预测性维护和自动驾驶汽车操作等工作。 什么是边缘计算? …

CMake 编译项目

一、概述 cmake 是C一个很重要的编译和项目管理工具&#xff0c;我们在git 上以及常见的项目现在多数都是用cmake 管理的&#xff0c;那么我们今天就做一个同时有Opencv和CGAL 以及PCL 的项目。 二、项目管理 重点是CMakeList.txt 1、CMakeList.txt cmake_minimum_requir…