掌握Spring5.X 面向切面编程AOP

AOP是一种编程范式,用于在不修改原有业务逻辑的情况下添加额外功能,如日志、事务管理。核心概念包括横切关注点、通知、切点、切面等。通知分为前置、后置、返回、异常和环绕五种类型。在Spring框架中,AOP通过代理实现,切入点表达式用于精确选择需要增强的方法。AOP在权限控制、日志和事务管理等场景下广泛应用。
摘要由CSDN通过智能技术生成

什么是AOP面向切面编程

Aspect Oriented Program ⾯向切⾯编程,在不改变原有逻辑上增加额外的功能,⽐如解决系统层⾯的问题,或者增加新的功能

场景:权限控制,缓存,⽇志处理,事务控制

AOP思想把功能分两个部分,分离系统中的各种关注点:
1、核心关注点,业务的主要功能
2、横切关注点,⾮核心、额外增加的功能

AOP面向切面编程核心概念

横切关注点

对哪些⽅法进⾏拦截,拦截后怎么处理,这些就叫横切关注点
⽐如:权限认证、⽇志、事物

通知 Advice

在特定的切⼊点上执⾏的增强处理,有5种通知
比如你需要记录日志,控制事务 ,提前编写好通⽤的模块,需要的地⽅直接调用

连接点 JointPoint

要⽤通知的地⽅,业务流程在运⾏过程中需要插⼊切⾯的具体位置,⼀般是⽅法的调用前后,全部⽅法都可以是连接点(只是概念)

切入点 Pointcut

不能全部⽅法都是连接点,通过特定的规则来筛选连接点, 就是Pointcut,选中那⼏个你想要的⽅法。
在程序中主要体现为书写切入点表达式(通过通配、正则表达式)过滤出特定的⼀组
JointPoint连接点
过滤出相应的 Advice 将要发⽣的joinpoint地⽅

切面 Aspect

通常是⼀个类,⾥⾯定义切⼊点+通知,定义在什么地⽅、什么时间点、做什么事情
通知advice指明了时间和做的事情(前置、后置等)
切入点 pointcut 指定在什么地方干这个事情

web接⼝设计中,web层->⽹关层->服务层->数据层,每⼀层之间也是⼀个切⾯,对象和对象,方法和方法之间都是⼀个个切⾯

目标 target

⽬标类,真正的业务逻辑,可以在⽬标类不知情的条件下,增加新的功能到⽬标类的链路上

织入 Weaving

把切⾯(某个类)应⽤到⽬标函数的过程称为织⼊

AOP代理

AOP框架创建的对象,代理就是目标对象的加强
Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理

AOP里面的通知Advice类型

@Before前置通知:在执行目标方法之前运行
@After后置通知:在目标方法运行结束之后
@AfterReturning返回通知:在目标方法正常返回值后运行
@AfterThrowing异常通知:在目标方法出现异常后运行
@Around环绕通知:在目标方法完成前、后做增强处理 ,环绕通知是最重要的通知类型 ,像事务,⽇志等都是环绕通知,注意编程中核心是⼀个ProceedingJoinPoint,需要⼿动执行joinPoint.procced()

面向切面编程实例

用户下单
核心关注点:创建订单
横切关注点:记录⽇志、控制事务

用户观看付费视频
核心关注点:获取播放地址
横切关注点:记录⽇志、权限认证

JoinPoint连接点:addOrder/ fndOrderByld/ delOrder/ updateOrderPointCut
切入点:过滤出那些 joinpoint中哪些目标函数进行切入
Advice 通知:在切入点中的函数上执行的动作,如记录日志、权限校验等
Aspect 切面:有切入点和通知组合而成,定义通知应用到那些切入点
Weaving 织入:把切面的代码应用到目标函数的过程

//⽬标类 VideoOrderService 
//⾥⾯每个⽅法都是连接点
//切⼊点是CUD类型的⽅法,R读取的不作为切⼊点
//CRDU全称:增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)
VideoOrderService{
 //新增订单
 addOrder(){ }
 //查询订单
 findOrderById(){}
 //删除订单
 delOrder(){}
 //更新订单
 updateOrder(){}
}

//权限切⾯类 = 切⼊点+通知
PermissionAspects{
 //切⼊点 定义了什么地⽅
 @Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")
 public void pointCut(){}

 //before 通知 表示在⽬标⽅法执⾏前切⼊, 并指定在哪个⽅法前切⼊
 //什么时候,做什么事情
 @Before("pointCut()")
 public void permissionCheck(){
     System.out.println("在 xxx 之前执⾏权限校验");
 }
 ....
}
//⽇志切⾯类 = 切⼊点+通知
LogAspect{
 //切⼊点 定义了什么地⽅
 @Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")
 public void pointCut(){}

 //after 通知 表示在⽬标⽅法执⾏后切⼊, 并指定在哪个⽅法前切⼊
 //什么时候,做什么事情
 @After("pointCut()")
 public void logStart(){
     System.out.println("在 xxx 之后记录⽇志");
 }
 ......
}

AOP切入点表达式

切入点表示式

除了返回类型、⽅法名和参数外,其它项都是可选的 (修饰符基本都是省略不写)

(必填)	    访问修饰符 		 返回值类型(必填)     包和类 		      ⽅法
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?namepattern(param-pattern) throws-pattern?)

@Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")

常见匹配语法

*:匹配任何数量字符单个
..:匹配任何数量字符,可以多个;在类型模式中匹配任何数量子包,在方法参数模式中匹配任何数量参数
() 匹配⼀个不接受任何参数的方法
(..) 匹配⼀个接受任意数量参数的方法
(*) 匹配了⼀个接受⼀个任何类型的参数的方法
(*,Integer) 匹配了⼀个接受两个参数的方法,其中第⼀个参数是任意类型,第⼆个参数必须是Integer类型

举例:
1、任意公共方法:execution(public * *(..))
2、任何⼀个名字以“save”开始的方法:execution(* save*(..))
3、VideoService接⼝定义的任意方法(识别):execution(* net.xdclass.service.VideoService.*(..))
4、在service包中定义的任意方法(识别):execution(* net.xdclass.service.*.*(..))
5、匹配 service 包,子孙包下所有类的所有方法(识别):execution(* net.xdclass.service..*.*(..))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆浆两块钱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值