Spring核心——面向切面编程(AOP)

news2024/11/20 9:23:03

Spring核心——AOP(Aspect-oriented programming)

  • 一、概念
  • 二、作用
  • 三、AOP核心概念
    • 1.连接点(JoinPoint)
    • 2.切入点(Pointcut)
    • 3.通知(Advice)
    • 4.通知类
    • 5.切面(Aspect)
    • 6.目标对象(Target)
    • 7.代理(Proxy)
  • 四、AOP概念(配合代码理解)
    • 1.连接点
    • 2.切入点
    • 3.通知
    • 4.通知类
    • 5.切面
  • 五、AOP实现步骤
    • 1.导入依赖
    • 2.定义接口、实现类
    • 3.定义通知、通知类
    • 4.定义切入点
    • 5.定义切面
    • 6.添加注解
    • 7.启动应用
  • 六、AOP工作流程
    • 1.启动spring容器
    • 2.读取切面配置中的切入点
    • 3.初始化Bean,判断对应类中的方法是否匹配到任意切入点
    • 回顾
      • 目标对象(Target)
      • 代理(Proxy)
    • 4.获取Bean执行方法
    • 5.验证是否代理对象


笔记于参考黑马2022版本的SSM课程

一、概念

面向切面编程,也叫面向方法编程,与面向对象编程(OOP)一样,都是一种编程思想,SpringAOP的底层通过代理模式实现。

二、作用

AOP可用于对业务逻辑的各个部分进行隔离,降低业务逻辑的耦合性,提高程序的可重用型和开发效率。

简单来说,就是在不改动原始设计的基础上为其功能进行增强。

三、AOP核心概念

1.连接点(JoinPoint)

连接点是程序执行过程中明确的点,比如方法调用、异常抛出、字段修改等。

SpringAOP中,可以理解为方法的执行

2.切入点(Pointcut)

匹配连接点的式子

在SpringAOP中,一个切入点可以描述一个具体方法,也可也匹配多个方法。

连接点与切入点关系:

切入点就是带有通知的连接点。
或者:切入点就是——有增强的方法。

连接点范围更大。属于切入点的方法,一定属于连接点;
属于连接点的方法不一定会被增强,因此可能不属于切入点。
(某个连接点满足执行要求时,该点将被连接增强处理,该连接点也就变成了切入点。)

3.通知(Advice)

在切入点处执行的操作,也就是共性功能

springAOP中,最终以“方法”呈现

4.通知类

定义通知的类

通知可以分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)、环绕通知(Around)五类。

例如:
在这里插入图片描述

5.切面(Aspect)

描述通知与切入点的对应关系。

切面通常是一个类,可以定义切入点和通知。

6.目标对象(Target)

原始功能去掉共性功能对应的类产生的对象。这种对象无法直接完成最终工作。它可以运行,但运行过程中,对于要增强的内容,是缺失的。

对哪个类做增强,这个类对应的对象就叫目标对象。

7.代理(Proxy)

目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现。
SpringAOP采用的是代理模式实现,所以要对原始对象进行增强,就需要对原始对象创建代理对象。

在代理对象中的方法把通知内容加进去,例如MyAdvice中的method方法,就实现了增强,即代理。

四、AOP概念(配合代码理解)

有代码如下

@Repository
public class BookDaoImpl implements BookDao {
    public void save() {
        //记录程序当前执行执行(开始时间)
        Long startTime = System.currentTimeMillis();
        //业务执行万次
        for (int i = 0;i<10000;i++) {
            System.out.println("book dao save ...");
        }
        //记录程序当前执行时间(结束时间)
        Long endTime = System.currentTimeMillis();
        //计算时间差
        Long totalTime = endTime-startTime;
        //输出信息
        System.out.println("执行万次消耗时间:" + totalTime + "ms");
    }
    public void update(){
        System.out.println("book dao update ...");
    }

    public void delete(){
        System.out.println("book dao delete ...");
    }

    public void select(){
        System.out.println("book dao select ...");
    }
}

1.连接点

我们希望让其他的方法也能够拥有save方法中的内容,于是将这部分代码抽取出来。
在这里插入图片描述

AOP中,原先的save(),update(),delete(),select()方法就称为连接点

在这里插入图片描述

2.切入点

利用切入点表达式,设置要追加功能的方法,这里设置带有“d”的方法名进行功能追加
在这里插入图片描述

@Component
@Aspect
public class MyAdvice {

    @Pointcut("execution(* com.example.dao.BookDao.*d*(..))")
    private void pt(){}

    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("------------------------------");
        Long startTime = System.currentTimeMillis();
        for (int i = 0 ; i<10000 ; i++) {
            //调用原始操作
            pjp.proceed();
        }
        Long endTime = System.currentTimeMillis();
        Long totalTime = endTime-startTime;
        System.out.println("执行万次消耗时间:" + totalTime + "ms");
        return null;
    }
}

这样一来,delete(),update()就是要追加功能的方法,这样的方法就是切入点。
而select()并没有追加功能,因此不属于切入点。

在这里插入图片描述

3.通知

之前被我们抽取出来的,用于存放共性功能的方法,便称为通知。
在这里插入图片描述

4.通知类

“通知”是一个方法,Java中,方法是不能独立存在的,因此,存放通知的类便成为通知类。
在这里插入图片描述

5.切面

未来写代码时,通知可能会有多个,切入点也会有多个,那么如何知道哪个通知对应哪个切入点?
为了将通知与切入点的关系绑定,搞清楚哪个切入点需要添加哪个通知,就需要“切面”将两者绑定。

在这里插入图片描述

五、AOP实现步骤

1.导入依赖

spring-aop以及aspectJ的包,spring-aop已经包括在了spring-context中,不需再单独导入。

	<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

2.定义接口、实现类

实现类BookDaoImpl

@Repository
public class BookDaoImpl implements BookDao {
	public void save() {
		System.out.println(System.currentTimeMillis());
		System.out.println("book dao save ...");
	}
	public void update(){
		System.out.println("book dao update ...");
	}
}

接口BookDao

public interface BookDao {
    public void save();
    public void update();
}

3.定义通知、通知类

根据之前的例子,通知就是将共有的功能抽取出来后形成的方法,这里沿用前面例子的方法,打印系统当前时间。类、方法名任意取。

public class MyAdvice {
	public void method(){
		System.out.println(System.currentTimeMillis());
	}
}

4.定义切入点

①在通知类中写一个私有方法,且没有参数、没有返回值、没有实际逻辑

private void pt(){}

②方法上,加上切入点表达式

//表示要增强的方法是update(),update()就是切入点
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}

5.定义切面

绑定切入点与通知的关系(切面)
在通知上添加注解,分为前置通知Before、后置通知AfterReturning、异常通知AfterThrowing、最终通知After、环绕通知Around

	@Before("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }

6.添加注解

通知类中
①使代码受spring控制——@Component
②告诉spring当做AOP进行处理——@Aspect

@Component
@Aspect
public class MyAdvice {
	...
}

③配置类里,加上@EnableAspectJAutoProxy,告诉spring,项目中有用注解开发的AOP

@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class SpringConfig {
	...
}

7.启动应用

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = ctx.getBean(BookDao.class);
        bookDao.update();
    }
}

可以看到update方法已增强。
在这里插入图片描述

六、AOP工作流程

1.启动spring容器

2.读取切面配置中的切入点

配置了的切入点,才会被读取
在这里插入图片描述

3.初始化Bean,判断对应类中的方法是否匹配到任意切入点

匹配失败,创建对象;
匹配成功,创建原始对象(目标对象)的代理对象

回顾

目标对象(Target)

原始功能去掉共性功能对应的类产生的对象。这种对象无法直接完成最终工作。它可以运行,但运行过程中,对于要增强的内容,是缺失的。

对哪个类做增强,这个类对应的对象就叫目标对象。例如BookServiceImpl类对应的对象

代理(Proxy)

目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现。
SpringAOP采用的是代理模式实现,所以要对原始对象进行增强,就需要对原始对象创建代理对象。

在代理对象中的方法把通知内容加进去,例如MyAdvice中的method方法,就实现了增强,即代理。

4.获取Bean执行方法

获取的bean是原始对象时,调用方法并执行,完成操作

获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作

5.验证是否代理对象

如果目标对象中的方法会被增强,那么容器中将存入的是目标对象的代理对象; 如果目标对象中的方法不被增强,那么容器中将存入的是目标对象本身。

修改MyAdvice中的切入点表达式,将update()改成其他名字,即不再增强update()方法,运行:
此时update方法没有被增强,IOC容器中的对象应该是目标对象本身。
在这里插入图片描述
改回update(),即增强update()方法,运行:
此时,容器中的对象应该是目标对象的代理对象。
在这里插入图片描述
注:直接打印对象,是通过对象的toString方法,无论该对象是否代理对象,打印的结果都是一样的,原因是内部对toString方法进行了重写。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/194476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c语言 结构体 动态内存 动态内存管理 模拟实现atoi 找单身狗 文件操作程序编译和链接 预处理 交换奇偶位 offsetof宏的实现 习题

结构体大小 【题目名称】 在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是&#xff08; C &#xff09; 对齐数是取其较小值 struct A {int a;short b;int c;char d; }; struct B {int a;short b;char c;int d; };【题目内容】 A. 1…

小程序项目学习--第五章:项目实战一

第五章&#xff1a;项目实战一、 01_(了解)音乐小程序的项目介绍 坑关于Vant Weapp中组件引入未找到的解决方案 [ pages/main-music/main-music.json 文件内容错误] pages/main-music/main-music.json: [“usingComponents”][“van-search”]: “vant/weapp/search/index”…

阿里云们扎堆集结,数据库黄金时代到了?

配图来自Canva可画 作为全球数一数二的信息产业大国&#xff0c;我国在信息技术软硬件底层标准、架构、产品以及生态体系方面&#xff0c;长期被外商“卡脖子”&#xff0c;其中数据库市场更是长期被甲骨文等外商公司所占据。 近年来伴随着信创产业的高速发展&#xff0c;国内…

第七章 idea集成git本地库操作

第一节 配置忽略文件 1、哪些文件需要忽略&#xff1f; 对于git来说可以忽略的文件 Eclipse工程特定文件 IDEA工IDEA工程特定文件 编译产生的二进制文件&#xff08;对于Maven工程来说就是target目录&#xff09; 2、为什么要忽略这些文件&#xff1f; 与项目的实际功能无…

巧用Golang泛型,简化代码编写

作者 | 百度小程序团队 导读 本文整理了很多的泛型应用技巧&#xff0c;结合具体的实际代码示例&#xff0c;特别是很多直接对Go语言内置的类库的实现进行改造&#xff0c;再通过两者在使用上直观对比&#xff0c;帮助大家对泛型使用思考上提供了更多思路&#xff0c;定会帮助大…

【教程】Python:IDLE开发环境安装与配置保姆级教学

【教程】Python&#xff1a;IDLE开发环境安装与配置保姆级教学下载地址安装步骤编写你的Python程序IDLE交互界面&#xff08;交互式运行&#xff09;IDLE编辑器&#xff08;文件式运行&#xff09;下载地址 请访问官网&#xff1a;python解释器安装 安装步骤 若安装最新版本…

FPGA的ADC信号采集ADS52J90-JESD204B接口

jesd204b实战操作笔记 本篇的内容是基于博主设计的jesd204b接口的ADC和FPGA的硬件板卡&#xff0c;通过调用jesd204b ip核来一步步在FPGA内部实现高速ADC数据采集&#xff0c;jesd204b协议和xilinx 的jesd204 IP核相关基本知识已在前面多篇文章中详细介绍&#xff0c;这里不再…

设计师们都在用的5款有限元分析软件推荐

最好的有限元分析软件可以让您测试物体如何受到外部因素的影响。例如&#xff0c;一家公司可以使用 FEA 软件来测试更新后的产品&#xff0c;看看它是否受到振动、热量和其他因素的影响。前 5 名有限元分析软件ANSYS - 具有基于任务的界面OpenFOAM - 可选择插值SimScale - 在线…

QT打包成windows软件

在QTCreator中将Debug模式切换到Release模式&#xff0c;进行编译在项目文件中找到Release模式构建的文件夹进入里面的有一个release的文件&#xff0c;这个文件里就是我们需要的东西进入里面&#xff0c;会有一个.exe的启动程序&#xff0c;但现在是启动不了的&#xff0c;需要…

常用不等式

整理自一个知乎大佬的回答Cauchy-Schwarz积分不等式在上可积,有:取等号的充要条件是存在常数,使得Hlder 积分不等式Minkowski 积分不等式Chebyshev 积分不等式设在上是连续函数,并且在上单调递增,则Kantorovich 积分不等式设函数均在区间上可积,且在上满足,则Jensen 积分不等式…

ES6迭代器 Iterator 详细介绍

文章目录前言一、Iterator二、迭代过程三、可迭代的数据结构3.1 Array3.2 String3.3 Map3.4 Set3.5 arguments总结前言 迭代器&#xff0c;是 ES6 引入的一种新的遍历机制&#xff0c;主要讲解的是 Iterator 、迭代过程、可迭代的数据结构。 一、Iterator Iterator 是 ES6 引…

MAC泛洪攻击-ARPDOS攻击-ARP Middleman攻击-IP地址欺骗-ICMP DOS 攻击

项目二 目录 文章目录一、搭建实验环境&#xff1a;1. 网络环境架构2. 实验环境与工具:3. 搭建两侧的局域网4. 搭建路由二、MAC泛洪攻击1. 实验环境2. 实验过程3. 实验分析&#xff1a;三、ARP DOS攻击1. 实验环境2. 实验过程3. 实验分析&#xff1a;四、ARP Middleman 攻击1. …

《SQL基础》08. 多表查询

SQL - 多表查询多表查询多表关系一对多多对多一对一多表查询概述分类内连接外连接自连接联合查询子查询分类标量子查询列子查询行子查询表子查询案例多表查询 多表关系 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#…

使用MySQL数据库,实现你的第一个JDBC程序

熟悉了JDBC的编程步骤后&#xff0c;接下来通过一个案例并依照上一小节所讲解的步骤来演示JDBC的使用。此案例会从tb_user表中读取数据&#xff0c;并将结果打印在控制台。需要说明的是&#xff0c;Java中的JDBC是用来连接数据库从而执行相关数据相关操作的&#xff0c;因此在使…

双面电子会议桌牌

产品特征&#xff1a; 超低功耗&#xff0c;3-5年电池寿命电子纸墨水屏幕&#xff0c;视角接近180多种电子桌牌显示颜色可选 3色&#xff08;黑&#xff0c;白&#xff0c;红&#xff09; 4色&#xff08;黑&#xff0c;白&#xff0c;红&#xff0c;黄&#xff09; 7色&…

营销大数据如何帮助企业深入了解客户—镭速

随着互联网的进一步发展&#xff0c;大门向您的企业敞开大门&#xff0c;让您在如何使用数据为客户提供他们所寻求的个性化&#xff0c;令人兴奋和引人入胜的体验方面更具创造性和创新性。大数据是了解客户究竟是谁以及如何与他们互动的关键部分。 行动中的见解 随着智能手机…

听劝,不要试图以编程为基础去学习网络安全

目录一、网络安全学习的误区1.不要试图以编程为基础去学习网络安全2.不要刚开始就深度学习网络安全3.收集适当的学习资料4.适当的报班学习二、学习网络安全的些许准备1.硬件选择2.软件选择3.外语能力三、网络安全学习路线第一阶段&#xff1a;基础操作入门第二阶段&#xff1a;…

什么是基站定位?

基站与信号塔首先&#xff0c;我们先介绍一下基站。基站包括移动、联通和电信基站&#xff0c;当手机开机、关机、切换基站时都会向最近最优基站赋权。其主要功能是负责用户手机端信号传出工作&#xff0c;包括语音通话、网络访问等各项业务。这里我们特别强调一个误区&#xf…

不离不弃生死相依

男孩儿&#xff1a;“对不起……” 女孩儿&#xff1a;“无所谓&#xff0c;你没什么对不起我的。” 键盘敲出最后这句话&#xff0c;女孩儿失声痛哭。 爱上他是女孩儿没有想到的事情&#xff0c;她以为自己不会爱上任何人。 可最后还是敌不过男孩儿的温柔&#xff0c;陷了进去…

OpenMMLab AI实战课笔记

1. 第一节课 1.1 计算机视觉任务 计算机视觉主要实现以下目标&#xff1a; 分类目标检测分割&#xff1a;语义分割、实例分割 (对像素进行精确分类, 像素粒度或细粒度)关键点检测 1.2 OpenMMLab框架 框架选择&#xff1a;PyTorchOpenMMLab是基于PyTorch开发的code base, …