AOP技术

news2025/1/14 17:56:10

目录

一、简介

1.1、OCP原则

1.2、AOP介绍及使用场景

二、AOP在项目中的使用

2.1、集成使用

2.2、定义全局异常通知

2.3、AOP注解的含义

2.4、多个切面的执行顺序

三、通知的执行顺序(基于spring-aop5版本)

四、常用的四种切入点表达式

4.1、bean表达式(常用)

4.2、annotation表达式(常用)

4.3、Execution表达式       

4.4、within表达式 

五、spring中的事务处理

5.1、概述

5.1、事务处理的位置

5.2、事务处理的两种方式

5.3、基于@Transactional 注解进行声明式事务管理的实现

5.4、代码中使用事务

5.5、@Transactional 注解解析

六、事务的传播特性

6.1、三种常用的事务传播属性


一、简介

1.1、OCP原则

                OCP开闭原则,对扩展开放,对修改关闭,在不改变原有系统核心业务代码的基础上动态添加一些扩展功能并可以控制对象的执行。

1.2、AOP介绍及使用场景

                AOP,面向切面编程,是一种设计思想,基于OCP(开闭原则),通过预编译方式和运行期动态代理方式,实现在不修改源码的情况下,添加额外的功能的一种技术。

                AOP 通常应用于日志处理,事务处理,权限处理,缓存处理等。

二、AOP在项目中的使用

2.1、集成使用

  1.  添加依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
  2. 通过注解实现
    @Slf4j
    @Component //交给spring管理
    @Aspect   //切面类型
    public class UserAspect {
    
        //该方法不需要写任何内容,该注解一般描述方法,在该方法上定义切入点
        @Pointcut("bean(userServiceImpl)")
        public void doPointCut(){}
    
        @Before("doPointCut()")
        public void doBefore(){log.info("doBefore");}
    
        @After("doPointCut()")
        public void doAfter(){log.info("doAfter");}
    
        @AfterReturning("doPointCut()")
        public void doAfterReturning(){log.info("doAfterReturning");}
    
    
        @AfterThrowing("doPointCut()")
        public void doAfterThrowing(){log.info("doAfterThrowing");}
    
        //定义环绕通知,优先级最高
        @Around("doPointCut()")
        public Object doAround(ProceedingJoinPoint point)throws Throwable{
            try {
                long t1=System.currentTimeMillis();
                Object obj=point.proceed();//调用本切面中的其他通知或者下一个切面的通知或者目标方法
                long t2=System.currentTimeMillis();
                log.info("方法执行时间:"+(t2-t1));
                return obj;
            }catch (Exception e){
                throw  e;
            }
        }
    }

执行结果: 

2.2、定义全局异常通知

@Component
@Slf4j
@Aspect
public class ExceptionAspect {
    @AfterThrowing(value = "bean(userServiceImpl)",throwing = "ex")
    public void doError(Exception ex){
        log.error(ex.getMessage());
    }
}

2.3、AOP注解的含义

@Aspect

定义一个切面
@PointCut定义切入点
通知类型@Around定义环绕通知
@Before定义前置通知
@After定义后置通知
@AfterReturning定义返回通知
@AfterThrowing定义异常通知

2.4、多个切面的执行顺序

        可以在切面类上添加@Order注解,同时可以添加具体的值,值越小,越优先,如下:BookUtil1切面先执行。

	@Aspect
	@Component
	@Order(1)
	public class BookUtil1 {
	}

	@Aspect
	@Component
	@Order(2)
	public class BookUtil2 {
	}

三、通知的执行顺序(基于spring-aop5版本)

  • 不同的版本执行顺序不一样

针对上面代码的代码,运行结果如下:

 分析图如下:

 

  1. around环绕通知是入口,它的优先级最高,然后回调用环绕通知中的Proceed方法,判断有没有前置通知;
  2. 如果定义了前置通知,此时进入before前置通知方法,执行完之后,此时会判断还有没有其他切面有环绕通知等,如果有继续执行,如果没有,则执行目标方法;
  3. 目标方法执行结束之后,判断有无异常,无异常执行return,有异常执行throw;
  4. 无论哪种情况,之后调用after后置通知方法;
  5. after后置通知方法执行完之后,调用环绕通知Proceed方法后面的代码;

四、常用的四种切入点表达式

4.1、bean表达式(常用)

  1. 该切入点只对userServiceImpl类中所有方法生效
    @Pointcut("bean(bookServiceImpl)")
  2. 指定所有后缀为ServiceImpl的类中的所有方法
    @Pointcut("bean(*ServiceImpl)")

4.2、annotation表达式(常用)

通过使用注解来修饰方法        

1、首先定义一个注解                                                                                                

@Retention(RetentionPolicy.RUNTIME)  //运行时有效
@Target(ElementType.METHOD) //该注解只能描述于方法
public @interface BookRequired {
}

2、 定义切面

@Slf4j
@Component //交给spring管理
@Aspect
public class BookAspect {

    @Pointcut("@annotation(com.example.springboot.annotation.BookRequired)")
    public void doPointCut(){}

    @Around("doPointCut()")
    public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
        log.info("---开始Around通知---");
        try {
            Object obj=joinPoint.proceed();
            log.info("---结束Around通知---");
            return obj;
        }catch (Throwable e){
            log.error(e.getMessage());
            throw e;
        }
    }
}

3、使用

    @BookRequired
    @Override
    public JsonResult getBookDetail(Integer bookId) {
        return new JsonResult().success();
    }

4.3、Execution表达式       

  1. 通用方法
    @Pointcut("execution(* com.example.springboot.service..*.*(..))")
    解析:  * 表示返回值;

                ** 表示service包以及它下面所有子包

                * 表示所有类中的所有方法

                (**)表示任意参数

    该表达式意思是,指定某目录下的所有的类中的所有方法

4.4、within表达式 

  1.  指定对bookServiceImpl类
     @Pointcut("within(com.example.springboot.service.impl.BookServiceImpl)")
  2. 指定目录下的所有的类
     @Pointcut("within(com.example.springboot.service.impl.*)")
  3. 指定当前目录及所有子目录下的类
     @Pointcut("within(com.example.springboot.service..*)")

五、spring中的事务处理

5.1、概述

  1.  spring框架中提供了一种声明式事务的处理方式,此方式基于AOP代理,可以将具体业务逻辑与事务处理进行解耦。也就是让我们的业务代码逻辑不受污染或少量污染,就可以实现事务控制。
  2. 在springBoot项目中,其内部提供了事务的自动配置,当我们在项目中添加了指定依赖spring-boot-starter-jdbc时,框架会自动为我们的项目注入事务管理器对象,最常用的为DataSourceTransactionManager对象。

5.1、事务处理的位置

        事务处理放在Service层,如果在dao层,回滚的时候只能回滚到当前方法,我们的service层的某个方法可能调用了dao层的好几个方法。如果在dao层,那dao层的所有被调用的方法都要commit,就会很繁琐。

5.2、事务处理的两种方式

  • Spring提供了两种事务管理方式, 编程式事务和声明式事务。编程式事务指的是通过编码方式实现事务;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。
  • Spring中声明式事务处理有两种方式,一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于@Transactional 注解的方式

5.3、基于@Transactional 注解进行声明式事务管理的实现

  1. 在配置类上添加注解@EnableTransactionManagement(有些spring版本不用加)
  2. 添加@Transactional注解到相关的类或方法上

5.4、代码中使用事务

  • 在类上添加该注解,表示类中所有的方法都使用事务,成功则提交,失败则回滚;
  • 在方法上添加该注解,表示该方法使用事务,成功则提交,失败则回滚
@Service
@Transactional(timeout = 30,readOnly = true,isolation = Isolation.READ_COMMITTED,rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
public class BookServiceImpl extends ServiceImpl<BookListMapper, BookList> implements BookService {
}

5.5、@Transactional 注解解析

timeout设置超时时间,超时之后回滚,如果不设置,底层会一直尝试提交,浪费资源
readOnly不写默认为false,表示该事务不是一个只读事务,类似于更新,修改的操作,我在修改更新的时候别人只能阻塞等待,设置为true,表示该事务是一个只读事务,查询的时候,一般设置为true,大家可以并发去读,锁的力度会比较小,
isolation事务隔离级别,多个事务可以并发执行,可能存在脏读,幻读等现象,一般设置为Isolation.READ_COMMITTED,表示一个事务读取的都是别人已提交过的数据,未提交的数据是看不到的
rollbackFor异常类型,表示遇到什么样的异常就会回滚
propagation事务的传播类型,业务是分开独立运行,还是可以一起混合执行,由他决定,

六、事务的传播特性

是指不同业务对象(不同service之间)中的事务方法之间的相互调用

6.1、三种常用的事务传播属性

  1. PROPAGATION_REQUIRED:(Spring默认)支持当前事务,如果当前没有事务,就新建一个事务;如果当前有事务,就参与当前事务。
  2. PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。新建事务与被挂起事务相互独立,互不影响。
  3. PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,就把当前事务挂起。

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

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

相关文章

【技术分享】手机端代理网络共享至win电脑端

【技术分享】手机端代理网络共享至win电脑端使用前提工具准备具体步骤1. 打开并实现安卓模拟器内的vP|n2. 打开并配置安卓模拟器内的Proxy Server3. 配置win的代理4. 完成使用前提 手机端具备代理功能&#xff0c;而电脑端不具备&#xff1b;希望电脑端使用手机端的代理功能上…

嵌入式技术之IAP,自从有了它老板再也不担心我的代码了!(中)

上篇文章我们一起学习了IAP的工作原理和IAP包含的3个重要功能&#xff1a;数据交互、数据存储和程序跳转。 这3个重要功能称为“IAP的三板斧”&#xff0c;接下来我们看这三板斧具体完成哪些细节工作&#xff0c;如何实现这三板斧。 1.数据交互 数据交互的功能是IAP核心功能…

Gson解析JSON

1.介绍 Gson是Google提供的处理JSON数据的Java类库&#xff0c;主要用于转换Java对象和JSON对象。 2.依赖 <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency><groupId>com.google.code.gson</groupId><artifac…

python协程--yield和yield from

字典为动词“to yield”给出了两个释义&#xff1a;产出和让步。对于 Python 生成器中的 yield 来说&#xff0c;这两个含义都成立。yield item 这行代码会产出一个值&#xff0c;提供给 next(...) 的调用方&#xff1b;此外&#xff0c;还会作出让步&#xff0c;暂停执行生成器…

Web应用怎样获取Access Token?

1.在联盟创建服务器应用 参考文档&#xff1a;开发准备 2.获取用户级Access Token 2.1 获取code 参考文档&#xff1a;接入华为帐号获取凭证 2.1.1 先按照跳转链接进行配置url https://oauth-login.cloud.huawei.com/oauth2/v3/authorize? response_typecode& acces…

docker(七)容器监控(CAdvisor+InfluxDB+Granfana)

docker可能会运行多个容器&#xff0c;一个宿主机上有多个容器时&#xff0c;需要监控容器的&#xff1a;CPU使用率&#xff0c;内存使用率&#xff0c;网络状态&#xff0c;磁盘空间等数据。 一、docker stats docker stats命令可以监控以下数据&#xff1a; 数据是实时的&…

FFmpeg简单使用:过滤器 ---- 视频过滤2

1. 简介 FFmpeg filter提供了很多⾳视频特效处理的功能&#xff0c;⽐如视频缩放、截取、翻转、叠加等。 其中定义了很多的filter&#xff0c;例如以下常⽤的⼀些filter。 scale&#xff1a;视频/图像的缩放 overlay&#xff1a;视频/图像的叠加 crop&#xff1a;视频/图像的裁…

新建unity项目

在此处点击新项目按钮&#xff0c;建立新的项目。 选择对应的项目模板和项目名称&#xff0c;位置。 项目新建会花费几分钟到十几分钟的时间。 新建完项目打开后就可以进入到unity引擎中。 新建项目会默认创建一个场景&#xff0c;场景保存在Assets--> Scenes中&#xff0c;…

服务器,只有“鞋盒”大小

上期,我们谈到了边缘端的远中近分类法,并介绍了戴尔科技集团最新发布的“远边缘”服务器PowerEdge XR4000。今天我们来继续说说这款服务器的奥秘。      服务器,只有“鞋盒”大小      PowerEdge XR4000代表了戴尔继续致力于边缘创新的承诺,它的大小只与鞋盒差不多,是P…

Java 集合有哪些内容?

今天我们就来简单的了解下java中的集合&#xff0c;有了解过得朋友都知道&#xff0c;也都用过&#xff0c;比如说做常用的List&#xff0c;还有Set、Map&#xff0c;而且像List和Set都是用于存储单列数据的集合&#xff0c;他们的父接口都是Conllection&#xff0c;List的特点…

hyperf中的缓存之CacheEvict

在开发中难免会遇到要批量删除一些缓存&#xff0c;hyperf的注解中提供了关于缓存的几个注解如下 Cacheable 生成缓存的&#xff0c;根据你的返回值生成缓存 参数($prefix, $value, $ttl, $listener, $offset, $group, $collect) CachePut 更新缓存 参数($prefix, $value, …

MS 训练笔记【1】:nnUNet

文章目录前言1. 安装2. 训练与测试2.1. 数据处理2.1.1. 整理数据路径2.1.2. 设置 nnFormer 读取文件的路径2.1.3. 数据集预处理2.2. 训练2.2.1. 训练代码2.2. 预测总结前言 nnUNet是德国癌症研究中心的工程师编写的框架&#xff0c;迄今为止依旧在维护和更新。本文主要记载 nn…

FBX模型

概览 fbx文件&#xff0c;一般是导出给unity使用的模型文件。 如下图所示&#xff0c;建立一个models目录&#xff0c;然后右击&#xff0c;选择 imoprt new asserts 即可导入这些文件。 展示如下&#xff0c;Mesh定义了形状。 铅笔也是同理&#xff0c;只不过铅笔有自己的贴图…

尚医通-前端列表(十一)

目录&#xff1a; &#xff08;1&#xff09;搭建前端环境 &#xff08;2&#xff09;目录结构和登录改造 &#xff08;3&#xff09;医院设置前端-列表 &#xff08;1&#xff09;搭建前端环境 vue-element-admin 简介 vue-element-admin是基于element-ui 的一套后台管理系…

计算机系统基础实验 - 数的机器级表示

实验1 数的机器级表示 实验序号&#xff1a;1 实验名称&#xff1a;数的机器级表示 适用专业&#xff1a;软件工程 学时数&#xff1a;2学时 一、实验目的 1.熟练掌握无符号整数的机器级表示 2.熟练掌握有符号整数的机器级表示 3.熟练掌握浮点数的机器级表示 二、实验要求 …

WORDPRESS WOOCOMMERCE购物网站安装AB跳转支付插件接口的教程

本文介绍在Wordpress Woocommerce购物系统上安装支付插件&#xff0c;并且对接《品牌出海AB跳转收单系统》的方法&#xff0c;以下是图文教程 注意本教程是采用Wordoress中文版本后台截取的图例&#xff0c;英文版本后台文字略有不同&#xff1b; 1、首先打开支付插件压缩包&…

反编译python 生成的exe源码

反编译python 生成的exe源码记录反编译exe工具使用 工具准备 – pyinstxtractor.py – uncompyle6 – sublime Text&#xff08;或者其他的二进制编辑工具&#xff09; 一、解包&#xff08;exe&#xff09; ①&#xff1a;先把下载的pyinstxtractor.py文件和需要进行反编译的…

π120M60代替ADuM2210SRIZ 双通道数字隔离器 电路简单速度快

π120M60代替ADuM2210SRIZ 双通道数字隔离器 电路简单速度快。具有出色的性能特征和可靠性&#xff0c;整体性能优于光耦和基于其他原理的数字隔离器产品。传输通道间彼此独立&#xff0c;可实现多种传输方向的配置&#xff0c;可实现 5.0kV rms 隔离耐压等级和 DC 到 10Mbps 信…

下载和安装MySQL官方提供的示例数据库(Employees)

一、前言 在此之前笔者写过一篇博客《你说精通MySQL其实很菜jī&#xff08;1&#xff09;&#xff1a;你不一定会的基本技巧或知识点&#xff08;值得一看&#xff09;》&#xff0c;本文内容是从那篇博客截取出来的。我们要学习MySQL相关的技术点&#xff0c;使用官方提供的测…

构造HTTP请求

构造HTTP请求一、浏览器自己构造二、通过 form 表单构造三、通过 ajax 构造一、浏览器自己构造 1&#xff09;地址栏里写URL&#xff0c;构造出GET请求 2&#xff09;点击a标签等&#xff0c;也会构造GET请求 3&#xff09;img、link、script也会构造GET请求 二、通过 form 表…