Spring AOP简介---01

AOP 概述

AOP 是什么?

AOP(Aspect Orient Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程(OOP)的一种补充和完善。它以通过预编译方式和运行期动态代理方式,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。如图-1所示:在这里插入图片描述
AOP与OOP字面意思相近,但其实两者完全是面向不同领域的设计思想。实际项目中我们通常将面向对象理解为一个静态过程(例如一个系统有多少个模块,一个模块有哪些对象,对象有哪些属性),面向切面的运行期代理方式,理解为一个动态过程,可以在对象运行时动态织入一些扩展功能或控制对象执行。

AOP 应用场景分析?

实际项目中通常会将系统分为两大部分,一部分是核心业务,一部分是非核业务。在编程实现时我们首先要完成的是核心业务的实现,非核心业务一般是通过特定方式切入到系统中,这种特定方式一般就是借助AOP进行实现。

AOP就是要基于OCP(开闭原则),在不改变原有系统核心业务代码的基础上动态添加一些扩展功能并可以"控制"对象的执行。例如AOP应用于项目中的日志处理,事务处理,权限处理,缓存处理等等。如图-2所示:
在这里插入图片描述

AOP 应用原理分析

Spring AOP底层基于代理机制实现功能扩展:

  1. 假如目标对象(被代理对象)实现接口,则底层可以采用JDK动态代理机制为目标对象创建代理对象(目标类和代理类会实现共同接口)。
  2. 假如目标对象(被代理对象)没有实现接口,则底层可以采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类型)。

Spring AOP 原理分析,如图-3所示:
在这里插入图片描述

说明:Spring boot2.x 中AOP现在默认使用的CGLIB代理,假如需要使用JDK动态代理可以在配置文件(applicatiion.properties)中进行如下配置:

spring.aop.proxy-target-class=false

AOP 相关术语分析

  • 切面(aspect): 横切面对象,一般为一个具体类对象(可以借助@Aspect声明)。
  • 通知(Advice):在切面的某个特定连接点上执行的动作(扩展功能),例如around,before,after等。
  • 连接点(joinpoint):程序执行过程中某个特定的点,一般指被拦截到的的方法。
  • 切入点(pointcut):对多个连接点(Joinpoint)一种定义,一般可以理解为多个连接点的集合。

连接点与切入点定义如图-4所示:
在这里插入图片描述

说明:我们可以简单的将机场的一个安检口理解为连接点,多个安检口为切入点,安全检查过程看成是通知。总之,概念很晦涩难懂,多做例子,做完就会清晰。先可以按白话去理解。

应用总结分析

在业务应用,AOP相关对象分析,如图-5所示:

在这里插入图片描述

扩展业务织入增强分析

基于JDK代理方式实现

假如目标对象有实现接口,则可以基于JDK为目标对象创建代理对象,然后为目标对象进行功能扩展,如图-6所示:
在这里插入图片描述
基于CGLIB代理方式实现
假如目标对象没有实现接口(当然实现了接口也是可以的),可以基于CGLIB代理方式为目标对象织入功能扩展,如图-7所示:
在这里插入图片描述
解析:

  1. 客户端向服务端发起一个请求,服务器端的Controller来处理这个请求.

  2. Controller处理请求,假如需要对这个请求做一定的业务处理,他可能要调用业务层对象. controller调用xxxService接口.的时候,实际运行时,要给这个接口注入一个实现类的对象.
    (最开始的路线是,Controller去访问我们的xxxService接口,xxxService去访问具体的实现类xxxServiceImpl,实现类去访问具体的dao)

  3. Controller运行时去访问我们的xxxService接口,service访问代理对象,(Controller是耦合于我们的service接口,其实注入的是我们代理对象,代理对象默认优先级高于目标对象,所以Controller运行时通过接口的引用访问代理对象)

  4. 代理对象访问我们的切面,

  5. 切面再调用我们的目标对象xxxServiceImpl,的方法,(jp.proceed())目标对象再访问我们的dao进行业务处理.

Spring AOP快速实践

业务描述

基于项目中的核心业务,添加简单的日志操作,借助SLF4J日志API输出目标方法的执行时长。(前提,不能修改目标方法代码-遵循OCP原则)

项目创建及配置

创建maven项目或在已有项目基础上添加AOP启动依赖:
在这里插入图片描述
在这里插入图片描述

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


创建日志切面类对象

将此日志切面类作为核心业务增强(一个横切面对象)类,用于输出业务执行时长,其关键代码如下:

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("after:{}",e.getMessage());
                   throw e;
                 }

         }

}

说明:

  • @Aspect 注解用于标识或者描述AOP中的切面类型,基于切面类型构建的对象用于为目标对象进行功能扩展或控制目标对象的执行。
  • @Pointcut注解用于描述切面中的方法,并定义切面中的切入点(基于特定表达式的方式进行描述),在本案例中切入点表达式用的是bean表达式,这个表达式以bean开头,bean括号中的内容为一个spring管理的某个bean对象的名字。
  • @Around注解用于描述切面中方法,这样的方法会被认为是一个环绕通知(核心业务方法执行之前和之后要执行的一个动作),@Aournd注解内部value属性的值为一个切入点表达式或者是切入点表达式的一个引用(这个引用为一个@PointCut注解描述的方法的方法名)。
  • ProceedingJoinPoint类为一个连接点类型,此类型的对象用于封装要执行的目标方法相关的一些信息。只能用于@Around注解描述的方法参数。

业务切面测试实现

启动项目测试或者进行单元测试,其中Spring Boot项目中的单元测试代码如下

@SpringBootTest

public class AopTests {
    
    

         @Autowired
         private SysUserService userService;

         @Test
         public void testSysUserService() {
    
    
                 PageObject<SysUserDeptVo> po=
                 userService.findPageObjects("admin",1);
                System.out.println("rowCount:"+po.getRowCount());
         }
}

猜你喜欢

转载自blog.csdn.net/weixin_48052161/article/details/108651671