AOP(Aspect Orient Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程(OOP)的一种补充和完善。它以通过预编译方式和运行期动态代理方式,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。如图
AOP与OOP字面意思相近,但其实两者完全是面向不同领域的设计思想。实际项目中我们通常将面向对象理解为一个静态过程(例如一个系统有多少个模块,一个模块有哪些对象,对象有哪些属性),面向切面的运行期代理方式,理解为一个动态过程,可以在对象运行时动态织入一些扩展功能或控制对象执行。
实际项目中通常会将系统分为两大部分,一部分是核心业务,一部分是非核业务。在编程实现时我们首先要完成的是核心业务的实现,非核心业务一般是通过特定方式切入到系统中,这种特定方式一般就是借助AOP进行实现。
AOP就是要基于OCP(开闭原则),在不改变原有系统核心业务代码的基础上动态添加一些扩展功能并可以"控制"对象的执行。例如AOP应用于项目中的日志处理,事务处理,权限处理,缓存处理等等。如图-2所示:
Spring AOP底层基于代理机制实现功能扩展:
假如目标对象(被代理对象)实现接口,则底层可以采用JDK动态代理机制为目标对象创建代理对象(目标类和代理类会实现共同接口)。
假如目标对象(被代理对象)没有实现接口,则底层可以采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类型)。
Spring AOP 原理分析,如图-3所示:
说明:Spring boot2.x 中AOP现在默认使用的CGLIB代理,假如需要使用JDK动态代理可以在配置文件(applicatiion.properties)中进行如下配置:
spring.aop.proxy-target-class=false
切面(aspect): 横切面对象,一般为一个具体类对象(可以借助@Aspect声明)。
通知(Advice):在切面的某个特定连接点上执行的动作(扩展功能),例如around,before,after等。
连接点(joinpoint):程序执行过程中某个特定的点,一般指被拦截到的的方法。
切入点(pointcut):对多个连接点(Joinpoint)一种定义,一般可以理解为多个连接点的集合。
连接点与切入点定义如图-4所示:
说明:我们可以简单的将机场的一个安检口理解为连接点,多个安检口为切入点,安全检查过程看成是通知。总之,概念很晦涩难懂,多做例子,做完就会清晰。先可以按白话去理解。
AOP启动依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
说明:基于此依赖spring可以整合AspectJ框架快速完成AOP的基本实现。AspectJ 是一个面向切面的框架,他定义了AOP的一些语法,有一个专门的字节码生成器来生成遵守java规范的class文件。
将此日志切面类作为核心业务增强(一个横切面对象)类,用于输出业务执行时长,其关键代码如下:
package com.cy.pj.common.aspect; @Aspect @Slf4j @Component public class SysLogAspect { @Pointcut("bean(sysUserServiceImpl)") public void logPointCut() {} @Around("logPointCut()") public Object around(ProceedingJoinPoint jp) throws Throwable{ try { log.info("start:"+System.currentTimeMillis()); Object result=jp.proceed();//调用下一个切面方法或目标方法 log.info("after:"+System.currentTimeMillis()); return result; }catch(Throwable e) { log.error(e.getMessage()); throw e; } } }
@Aspect 注解用于标识或者描述AOP中的切面类型,基于切面类型构建的对象用于为目标对象进行功能扩展或控制目标对象的执行。
@Pointcut注解用于描述切面中的方法,并定义切面中的切入点(基于特定表达式的方式进行描述),在本案例中切入点表达式用的是bean表达式,这个表达式以bean开头,bean括号中的内容为一个spring管理的某个bean对象的名字。
@Around注解用于描述切面中方法,这样的方法会被认为是一个环绕通知(核心业务方法执行之前和之后要执行的一个动作),@Aournd注解内部value属性的值为一个切入点表达式或者是切入点表达式的一个引用(这个引用为一个@PointCut注解描述的方法的方法名)。
ProceedingJoinPoint类为一个连接点类型,此类型的对象用于封装要执行的目标方法相关的一些信息。一般用于@Around注解描述的方法参数。
原文:https://www.cnblogs.com/wangjincai/p/13348201.html