Spring AOP 概述
#1、背景&定义
1.1 背景
软件开发一直在寻求一种高效开发、护展、维护的方式。从面向过程的开发实践中,对行为和属性进行聚合,形成了面向对象的开发思想。
例:我们会对API进行抽象成四个模块:Controller、Service、Gateway、Command。这很好地解决了业务级别的开发,但对于系统级别的开发我们很难聚焦。但对于每一个模块需要进行打日志、代码监控、异常处理等需求却较难实现(以打日志为例,我只能将日志代码嵌套在各个对象上,而无法关注日志本身),往往代码间高度耦合,这种现象又违背了OOP思想。
解决方案:
AOP示例
为了能够更好地将系统级别的代码抽离出来,去掉与对象的耦合,就产生了面向AOP(面向切面);进一步将系统级别的代码抽象出来,进行纵向排列,实现低耦合。
1.2 定义
AOP(Aspect-Oriented Programming, 面向切面编程),基本单元是 Aspect(切面),横向
OOP( Object-Oriented Programming, 面向对象编程) ,基本单元是Class(类),纵向
#2、术语
2.1 Pointcut(切入点)
在哪个地方进行切入,可以指定某一个点,也可以指定多个点。
例:类A的methord函数,可以同时指定多个类的多个函数(一般的AOP会采用多用方式来定义PointCut,比如说利用正则表达式)。
2.2 Advice(通知)
在切入点干什么,指定在PointCut地方做什么事情(原有业务逻辑之上的增强),打日志、执行缓存、处理异常等等。
2.3 Advisor/Aspect(切面)
PointCut + Advice 形成了切面Aspect
2.4 Proxy(AOP代理)
将切面植入到代码中,管理AOP如何融入OOP,思想的践行者却是Proxy,也是实现AOP的难点与核心据在。
2.5 Target Object(目标对象)
包含连接点的对象,也被称作被通知或被代理对象。
2.6 Joinpoint(连接点)
单个切入点
2.7 Weaving(编织)
组装连接点集合(Pointcut)来创建一个Advice(被通知对象)。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
术语示例#3、切入方式
3.1 Before :在所拦截方法执行前执行;
3.2 After :在所拦截方法执行后执行;
3.3 AfterRuturning :在所拦截方法返回值后,执行;
3.4 AfterThrowing :当所拦截方法抛出异常时,执行;
3.5 Around :最为复杂的切入方式。
区别:类似于try-catch-finally,拦截方法不管是否有异常,都会执行的是After的切入方式;AfterRuturning只有当拦截方法成功执行才会执行;AfterThrowing只有当拦截方法异常才会执行。
#4、切入顺序
单切面执行顺序 多切面执行顺序 如果在同一个 aspect 类中,针对同一个 pointcut,定义了两个相同的 advice(比如,定义了两个 @Before),那么这两个 advice 的执行顺序是无法确定的,需要@Order注解控制执行顺序 。
对于@Around这个advice,不管它有没有返回值,但是必须要方法内部,调用一下 ProceedingJoinPoint proceed()方法;否则无法链接后续的内容(链接Aspect、controller等)。