Spring第七天(AOP)

简介

AOP(Aspect Oriented Programing)面向切面编程,一种编程范式,指导开发者如何组织程序结构

作用

不惊动原始设计的基础上为其进行功能增强

Spring理念:无入侵式/无侵入式

基本概念

连接点(JoinPoint) : 程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等

        在SpringAOP中,理解为方法的执行

切入点(Pointcut) : 匹配连接点的式子

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

                一个具体方法:e.g.:dao类中的save方法

                匹配多个方法:所有的save方法,所有以get开头的方法,所有以Dao结尾的接口中的任                  意方法,所有带有一个参数的方法

通知(Advice) : 在切入点执行的操作,也就是共性功能

        在SpringAOP中,功能最终以方法的形式呈现

通知类:定义通知的类

切面(Aspect) : 描述通知与切入点的对应关系

实现案例

第一步、导入相关坐标

    <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>

第二步、定义dao接口与其实现类

package com.cacb.dao.impl;import com.cacb.dao.BookDao;
import org.springframework.stereotype.Repository;@Repository
public class BookDaoImpl implements BookDao {@Overridepublic void save() {System.out.println(System.currentTimeMillis());System.out.println("BookDao saving!");}@Overridepublic void update() {System.out.println("BookDao updating!");}
}

第三步、定义通知类,制作通知

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

第四步、在通知类中定义切入点

public class MyAdvice {@Pointcut("execution(void com.cacb.dao.BookDao.update())")private void pt(){}public void method(){System.out.println(System.currentTimeMillis());}
}

注:

切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,方法体无实际逻辑

第五步、在通知类中绑定切入点预通知关系,并指定通知添加到原始连接点的具体执行位置

public class MyAdvice {@Pointcut("execution(void com.cacb.dao.BookDao.update())")private void pt(){}@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());}
}

第六步、定义通知类受Spring容器管理,并定义当前类为切面类 

@Component
@Aspect
public class MyAdvice {@Pointcut("execution(void com.cacb.dao.BookDao.update())")private void pt(){}@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());}
}

第七步、在Spring核心配置文件中开启Spring对AOP注解驱动支持

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

AOP工作流程

1.Spring容器启动

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

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

        匹配失败,则创建对象

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

4.获取Bean执行方法

        获取Bean,调用方法并执行,完成操作

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

目标对象(Target) : 原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的

代理(Proxy) : 目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现

APO切入点表达式

切入点:要进行增强的方式

切入点表达式:要进行增强的方法的描述方式

以上例update()方法为例,共有两种描述方式

方式一:接口方式

@Pointcut("execution(void com.cacb.dao.BookDao.update())")

方式二:实现类方式

@Pointcut("execution(void com.cacb.dao.impl.BookDaoImpl.update())")

切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名 (参数)异常名)

动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点

访问修饰符:public,private等,可以省略

异常名:方法定义中抛出指定异常,可以省略

通配符

可以使用通配符描述切入点,快速描述

 * 单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

execution(public * com.cacb.*.UserService.find* (*))

匹配com.cacb包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

.. 多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

execution(public User com..UserService.findById (..))

匹配com包下的任意包中的UserService类或者接口中的所有名称为findById的方法

+ 专用于匹配子类类型

execution(* * ..*Service+.* (..))

AOP通知类型

AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置

AOP通知共分为五种类型

前置通知

@Before("")

后置通知

@After("")

环绕通知

    @Around("")public void around(ProceedingJoinPoint pjp) throws Throwable{//..原方法前操作pjp.proceed(); //表述对原始操作的调用//..原方发后操作}

如果原方法有返回值 

    @Around("")public Object around(ProceedingJoinPoint pjp) throws Throwable{//..原方法前操作Object result = pjp.proceed(); //表述对原始操作的调用//..原方法后操作return result}

返回后通知

@AfterReturning("")

只有在调用方法没有抛出异常,正常运行结束后该通知才会运行 

抛出异常后通知

@AfterThrowing("")

只有在调用方法抛出异常后才会运行

@Around注意事项

1.环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知

2.通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行

3.对原始方法的调用可以不接收返回值,通知方法设置成void即可,如果接收返回值,必须设定为Object类型

4.原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void,也可以设置成Object

5.由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须抛出Throwable对象

AOP通知获取数据

获取参数

JoinPoint:适用于前置、后置、返回后、抛出异常后通知

ProceedingJoinPoint:适用于环绕通知

获取返回值

返回后通知

环绕通知

获取异常

抛出异常后通知

 

环绕通知

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用 OpenCV 扫描图像、查找表和时间测量

目标 我们将寻求以下问题的答案&#xff1a; 如何浏览图像的每个像素&#xff1f;OpenCV 矩阵值是如何存储的&#xff1f;如何衡量我们算法的性能&#xff1f;什么是查找表&#xff0c;为什么要使用它们&#xff1f; 我们的测试用例 让我们考虑一种简单的颜色减少方法。通过…

令牌桶算法与Guava的实现RateLimiter源码分析

令牌桶算法与Guava的实现RateLimiter源码分析 令牌桶RateLimiter简介RateLimiter使用示例导入maven依赖编写测试代码 RateLimiter的实现源码解析SmoothRateLimiterSmoothBursty恒速获取令牌acquire(int)tryAcquire(int,long,TimeUnit) 存量桶系数小结 优缺点与漏桶的区别总结 令…

Go 知识slice

Go 知识slice 1. 什么是slice2. slice 基础2.1 定义 2.2 实现原理2.2.1 make 创建2.2.2 切片 创建 2.3 操作2.3.1 append 追加2.3.2 表达式切片2.3.3 扩展表达式2.3.4 扩容2.3.5 拷贝 3. 测试一下3.1 len && cap3.2 append && 扩容3.3 切片表达式 1. 什么是sli…

Spring第六天(注解开发第三方Bean)

注解开发管理第三方Bean 显然&#xff0c;我们无法在第三方Bean中写入诸如service这样的注解&#xff0c;所以&#xff0c;Spring为我们提供了Bean这一注解来让我们通过注解管理第三方Bean 第二种导入方式由于可读性太低&#xff0c;故只介绍第一种导入方式&#xff0c;这里我…

外包干了5个月,技术退步明显...

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

内网安全管理系统(保密管理系统)

在当今信息化的时代&#xff0c;企业的内网已经成为其核心资产的重要组成部分。 随着企业的快速发展和信息化程度的提升&#xff0c;内网安全问题日益凸显&#xff0c;如何保障内网的安全和机密信息的保密性&#xff0c;已经成为企业亟待解决的问题。 内网安全管理系统(保密管…

第11章 GUI Page507 步骤三十五:处理应用退出事件

为wxFrame&#xff0c;生成一个EVT_CLOSE事件响应函数&#xff1a; 实现如下&#xff1a; 运行效果&#xff1a;关闭时&#xff0c;会弹出对话框询问是否保存

(蓝桥杯每日一题)love

问题描述 马上就要到七夕情人节了&#xff0c;小蓝在这天想要心爱得男神表白&#xff0c;于是她写下了一个长度为n仅由小写字母组成的字符串。 她想要使这个字符串有 1314个 love 子序列但是马虎的小蓝却忘记了当前已经有多少个子序列为 love。 请你帮小蓝计算出当前字符串有多…

初识MQ-同步异步

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、同步通讯二、异步通讯2.1.异步调用方案2.2.异步的优缺点 三、什么时MQ3.1 mq和broker3.2几种mq的优缺点对比 总结 前言 一、同步通讯 同步调用问题&#…

Spring Boot框架中Controller层API接口如何支持使用多个@RequestBody注解接受请求体参数

一、前言 众所周知&#xff0c;在Spring Boot框架中&#xff0c;Controller层API接口编码获取请求体参数时&#xff0c;在参数上会使用RequestBody注解&#xff1b;如果一次请求中&#xff0c;请求体参数携带的内容需要用多个参数接收时&#xff0c;能不能多次使用RequestBody…

【从零到一AIGC源码解析系列1】文本生成图片Stable Diffusion的diffusers实现

目录 1. 如何使用 StableDiffusionPipeline 1.1环境配置 1.2 Stable Diffusion Pipeline 1.3生成非正方形图像 2. 如何使用 diffusers 构造自己的推理管线 关注公众号【AI杰克王】 Stable Diffusion是由CompVis、StabilityAl和LAION的研究人员和工程师创建的文本到图像潜在…

《Linux高性能服务器编程》笔记01

Linux高性能服务器编程 本文是读书笔记&#xff0c;如有侵权&#xff0c;请联系删除。 参考 Linux高性能服务器编程源码: https://github.com/raichen/LinuxServerCodes 豆瓣: Linux高性能服务器编程 文章目录 Linux高性能服务器编程第05章 Linux网络编程基础API5.1 socket…