Spring学习 | AOP
admin
2024-03-27 11:15:33
0

文章目录

  • 一、简介
  • 二、AOP操作
    • 2.1 操作术语
    • 2.2 操作实现
      • 2.2.1 实现原理
      • 2.2.2 具体实现


学习视频🎥:https://www.bilibili.com/video/BV1Vf4y127N5

一、简介

💬概述:Aspect Oriented Programming 面向切面(方面)编程,意思是不通过修改源代码的方式,在主干功能上添加新的功能

🔑作用与目的:利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

🔑AOP底层原理:AOP底层通过动态代理实现,根据有无接口将动态代理分为两种——JDK和CGLIB

❓ 动态代理:代理模式的实现方式之一,即在在内存中形成代理类

  1. JDK动态代理:需要增强的是接口中的方法,则要创建对应接口的实现类代理对象,通过实现类代理对象增强方法功能,可以通过Proxy 类来实现
  2. CGLIB动态代理:需要增强的是普通类(POJO)的方法,则要创建对应类的子类代理对象,通过子类代理对象增强方法的功能

二、AOP操作

2.1 操作术语

  • 连接点(Joinpoint):可以被增强的方法
  • 切入点(Pointcut):实际被增强的方法
  • 通知、增强(Advice):实现增强功能的逻辑部分(增强代码),有5种通知类型
    ① 前置通知:在被增强的方法前执行
    ② 后置通知(返回通知):在被增强的方法后(方法返回值之后)执行,如果方法出现异常可能不会执行
    ③ 环绕通知:在被增强的方法前后都执行
    ④ 异常通知:被增强的方法出现异常时执行
    ⑤ 最终通知:在被增强的方法后执行,类似于finally语句,即不管被增强的方法是否出现异常都会执行
  • 切面:表示一个动作——将通知应用到切入点上(实现增强功能)

2.2 操作实现

2.2.1 实现原理

🔑基于AspectJ:Spring AOP一般都是基于AspectJ 实现的

💡 AspectJ 不是Spring的组成部分,实际上是对AOP编程思想的一个实践,

🔑切入点表达式:在进行AOP的配置时,需要使用切入点表达(作为属性值)

🔑作用指定和标识出需要增强的类和方法

🔑语法格式execution([权限修饰符] [返回类型] [被增强的类的全类名].[被增强的方法名](参数列表));

  • 权限修饰符一般用 *代替,表示全部权限修饰符都符合
  • 返回类型可以省略
  • 参数列表用..代替

🔑案例(用*表示所有)

  • 标识出具体的被增强类和被增强方法:execution(* com.Key.dao.UserDao.add(..));
  • 标识出具体的被增强类,类中所有方法都被增强:execution(* com.Key.dao.UserDao.*(..));
  • 只标识出具体的包,包中所有类和类中所有方法都被增强:execution(* com.Key.dao.*.*(..));

🔑导入相关jar包:spring-aspects-…jar、com.springsource.net.sf.cglib-…jar、com.springsource.org.aopalliance-…jar、com.springsource.org.aspectj.weaver-…jar

2.2.2 具体实现

🔑注解方式实现(重点)

① 创建需要被增强的类和方法

② 创建增强类,在类中创建多个方法,通过在方法上添加注解,使每个方法对应不同的通知类型(5种)

💡 以上每个注解中都有一个属性value属性值就是切入点表达式,通过切入点表达式精确找到被增强类和方法

  • @Before:对应前置通知

    // 前置通知
    @Before(value = "execution(* com.Key.bean.User.add(..))")
    public void before() {System.out.printf("增强方法——前置通知");
    }
    
  • @AfterReturning:对应后置通知(返回通知)

    // 后置通知
    @AfterReturning(value = "execution(* com.Key.bean.User.add(..))")
    public void afterReturning() {System.out.printf("增强方法——后置通知");
    }
    
  • @Around:对应环绕通知

    💡 环绕通知在被增强方法前后都执行,则需要添加一个形参ProceedingJoinPoint proceedingJoinPoint,然后调用该形参的方法——proceed()执行被增强的方法

    // 环绕通知
    @Around(value = "execution(* com.Key.bean.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.printf("方法前执行");// 执行被增强的方法proceedingJoinPoint.proceed();System.out.printf("方法后执行");
    }
    
  • @AfterThrowing:对应异常通知

    // 异常通知
    @AfterThrowing(value = "execution(* com.Key.bean.User.add(..))")
    public void afterThrowing() {System.out.printf("增强方法——异常通知");
    }
    
  • @After:对应最终通知

    // 最终通知
    @After(value = "execution(* com.Key.bean.User.add(..))")
    public void after() {System.out.printf("增强方法——最终通知");
    }
    

③ 实现通知(增强)的配置

  • 在spring 配置文件中开启组件扫描(使用注解的必须操作)

    
    
  • 使用注解创建出被增强类对象以及增强类对象:在对应类上添加@Component注解即可

    // 创建被增强类对象
    @Component(value = "user")
    public class User {// 被增强方法public void add() {System.out.println("被增强方法...");}
    }/*+----------------------------------------------------+*/// 创建增强类对象
    @Component(value = "userProxy")
    public class UserProxy {// 增强方法(前置通知)@Before(value = "execution(* com.Key.bean.User.add(..))")public void before() {System.out.printf("增强方法——前置通知");}
    }
    
  • 使用注解创建代理对象:在增强类上添加@Aspect注解

    // 创建增强类对象并创建出对应的代理对象
    @Component(value = "userProxy")
    @Aspect
    public class UserProxy {// 增强方法(前置通知)@Before(value = "execution(* com.Key.bean.User.add(..))")public void before() {System.out.printf("增强方法——前置通知");}
    }
    
  • 开启代理对象

    1️⃣. xml 文件配置:先开启aop 名称空间,再使用标签

    
    

    2️⃣. 使用注解(完全注解开发):创建配置类,在配置类上添加@EnableAspectJAutoProxy,注解中添加proxyTargetClass属性,属性值置为true(默认是false)

    @Configuration
    @ComponentScan(basePackage = {"com.Key"})
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class SpringConfig {// code...
    }
    

④ 抽取公共切入点

  • 使用:在增强类中创建一个方法pointCut(),方法上添加@Pointcut注解,注解中添加value属性(可省略),属性值就是抽取出来的公共切入点表达式,将含有公共切入点表达式的增强方法上的表达式都改成pointCut()即可

    // 抽取公共切入点
    @Pointcut(value = "execution(* com.Key.bean.User.add(..))")
    public void pointCut() {// code...
    }@After(value = "pointCut()")
    public void after() {// code...
    }
    
  • 作用:减少冗余的表达式,而且修改表达式时只需要修改一处即可

⑤ 设置增强类优先级:当有多个增强类对同一个类及其方法进行增强时,需要对每个增强类设置优先级。在每个增强类上添加@Order注解,注解中添加一个整数值,该数值越小优先级越高

// 设置优先级为1的增强类
@Component("uP")
@Aspect
@Order(1)
public class UserProxy {@Beforepublic void before() {System.out.println("增强方法");}
}

🔑xml 文件配置(了解即可)

① 创建被增强类和增强类,以及各自的方法

② 在spring 配置文件中创建被增强类对象和增强类对象




③ 在spring 配置文件中配置切入点:需要先引入aop 名称空间




相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...