当前位置: 首页 > news >正文

用spring-boot-starter实现事务的统一配置

一、前言

微服务架构下,多个微服务都需要事务操作,如果在每个微服务下都从头配置事务,将非常繁锁。事务配置具有高度的一致性,可以抽取出来,制作starter,在需要配置事务的服务中引入starter依赖即可。

  • 采用springAOP的方式实现事务

  • 制作过程可以参考:

    • 自定义启动器 Starter【保姆级教程】
    • 用starter实现Oauth2中资源服务的统一配置

二、制作starter

1、完整结构图

在这里插入图片描述

2、引用模块

名称:tuwer-transaction-spring-boot-starter

引用模块用于外部引用。只有pom.xml文件

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tuwer</groupId><artifactId>tuwer-transaction-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version><description>事务starter</description><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><!-- 编译编码 --><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- 自动配置模块 --><dependency><groupId>com.tuwer</groupId><artifactId>tuwer-transaction-spring-boot-starter-autoconfigure</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
</project>

3、自动配置模块

名称:tuwer-transaction-spring-boot-starter-autoconfigure\

1> pom.xml

使用jdbc的事务管理器

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.7</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.tuwer</groupId><artifactId>tuwer-transaction-spring-boot-starter-autoconfigure</artifactId><version>1.0-SNAPSHOT</version><description>事务starter自动配置模块</description><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><!-- 编译编码 --><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- 基础启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- aop --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- 数据库 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency></dependencies>
</project>

2> 切入点属性类

  • 用于外部配置切入点

  • 可以配置多个

  • 如果没有配置,就使用默认的:execution(* com.tuwer.service..*Impl.*(..)),【com.tuwer.service】包及子包下,所有以【Impl】结尾的类的所有方法

package com.tuwer.config;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.CollectionUtils;import java.util.HashSet;
import java.util.Set;/*** <p>事务属性类</p>** @author 土味儿* Date 2023/4/17* @version 1.0*/
@ConfigurationProperties(prefix = "tuwer-transaction")
public class TransactionProperty {/*** 切入点(可以有多个)* 格式必须符合要求*/private Set<String> pointcut = new HashSet<>();/*** 获取切入点表达式(可以有多个组合)* -----------------------------------* execution(...) || execution(...)* -----------------------------------* @return*/public String getPointcutExpression() {// 如果set集合为null,或没有值时,使用默认值if(CollectionUtils.isEmpty(this.pointcut)){// 默认切入点:【com.tuwer.service】包及子包下,所有以【Impl】结尾的类的所有方法return "execution(* com.tuwer.service..*Impl.*(..))";}StringBuilder sb = new StringBuilder();// 组合多个切入点for (String p : this.pointcut) {sb.append(" || ").append("execution(").append(p).append(")");}// 组合后,去除最前面的" || "返回return sb.substring(3);}public void setPointcut(Set<String> pointcut) {this.pointcut = pointcut;}
}

外部配置切入点示例:

由于切入点中有特殊字符*,所以需要加入引号:单引号或双引号都可以

# 事务切入点
tuwer-transaction:pointcut:- '* com.tuwer1231.service..*Impl.*(..))'- '* com.tuwer.service123..*Impl.*(..))'- '* com.tuwer345.service123..*Impl.*(..))'

3> 切面自动配置类

package com.tuwer.config;import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;import javax.annotation.Resource;/*** <p>事务自动配置类</p>** @author 土味儿* Date 2023/4/17* @version 1.0*/
@Aspect
@Configuration
@EnableConfigurationProperties(TransactionProperty.class)
public class TuwerTransactionAutoConfiguration {/*** 注入 TransactionProperty 属性配置类*/@Resourceprivate TransactionProperty transactionProperty;/*** 注入事务管理器*/@Resourceprivate TransactionManager transactionManager;/*** 定义事务增强** @return*/@Beanpublic TransactionInterceptor txAdvice() {NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();// 查询等;只读DefaultTransactionAttribute readonlyAttr = new DefaultTransactionAttribute();readonlyAttr.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);readonlyAttr.setReadOnly(true);source.addTransactionalMethod("get*", readonlyAttr);source.addTransactionalMethod("select*", readonlyAttr);source.addTransactionalMethod("query*", readonlyAttr);source.addTransactionalMethod("load*", readonlyAttr);source.addTransactionalMethod("search*", readonlyAttr);source.addTransactionalMethod("find*", readonlyAttr);source.addTransactionalMethod("list*", readonlyAttr);source.addTransactionalMethod("count*", readonlyAttr);source.addTransactionalMethod("is*", readonlyAttr);// 增删改DefaultTransactionAttribute otherAttr = new DefaultTransactionAttribute();otherAttr.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);source.addTransactionalMethod("*", otherAttr);return new TransactionInterceptor(transactionManager, source);}/*** 织入事务** @return*/@Beanpublic Advisor txAdviceAdvisor() {// 切入点AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression(transactionProperty.getPointcutExpression());return new DefaultPointcutAdvisor(pointcut, txAdvice());}
}

4> spring.factories

指明自动配置类的地址,在 resources 目录下编写一个自己的 META-INF\spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.tuwer.config.TuwerTransactionAutoConfiguration

5> Install

把starter安装install到本地maven仓库中

三、使用说明

1、引入starter依赖

<!-- 事务starter -->
<dependency><groupId>com.tuwer</groupId><artifactId>tuwer-transaction-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

2、配置切入点

如果不配置,就使用默认的切入点;此步骤可以省略。

至此,事务配置就OK了!

相关文章:

用spring-boot-starter实现事务的统一配置

一、前言 微服务架构下&#xff0c;多个微服务都需要事务操作&#xff0c;如果在每个微服务下都从头配置事务&#xff0c;将非常繁锁。事务配置具有高度的一致性&#xff0c;可以抽取出来&#xff0c;制作starter&#xff0c;在需要配置事务的服务中引入starter依赖即可。 采用…...

C语言中fopen的详细用法

fopen是C语言中用于打开文件的函数&#xff0c;其原型为&#xff1a; FILE *fopen(const char *filename, const char *mode); 其中&#xff0c;filename是要打开的文件名&#xff0c;mode是打开文件的模式。fopen函数返回一个指向FILE类型的指针&#xff0c;该指针指向打开的…...

C语言——学生信息管理系统(数组)

文章目录 一、前言二、目的三、框架1.菜单1.1主菜单1.2子菜单 2.流程图2.1总流程图2.2开始流程图2.3增加学生信息流程图2.4.删除学生信息流程图2.5修改学生信息流程图2.6查询学生信息流程图2.7对学生信息排序流程图 3.思路 四、代码五、演示视频 一、前言 因为最近是在赶进度总…...

【C语言】基础语法1:变量和数据类型

下一篇&#xff1a;运算符和表达式 ❤️‍&#x1f525;前情提要❤️‍&#x1f525;   欢迎来到C语言基本语法教程   在本专栏结束后会将所有内容整理成思维导图&#xff08;结束换链接&#xff09;并免费提供给大家学习&#xff0c;希望大家纠错指正。本专栏将以基础出发…...

linux安装和使用jekins

Jenkins详细安装配置部署--超详细_jenkins安装部署_宝贝富贵猪的博客-CSDN博客 1.安装JDK 2.获取安装包 下载页面&#xff1a;https://jenkins.io/zh/download/ 或者Index of /jenkins/redhat/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 3.安装Jenkins sud…...

驼峰式匹配

问题&#xff1a; 如果我们可以将小写字母插入模式串 pattern 得到待查询项 query&#xff0c;那么待查询项与给定模式串匹配。&#xff08;我们可以在任何位置插入每个字符&#xff0c;也可以插入 0 个字符。&#xff09; 给定待查询列表 queries&#xff0c;和模式串 patte…...

第三十七章 立方体贴图总结

立方体贴图:将多个纹理组合起来映射到一张纹理上的一种纹理类型。 一个立方体贴图时包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面,相当于是一个有纹理的立方体。 创建立方体贴图: 首先需要生成一个纹理,将其绑定到纹理目标上,再做其他纹理操作。补充:绑定到…...

哈希(C++)

哈希 unordered系列关联式容器unordered_map介绍 底层结构哈希概念哈希冲突哈希函数哈希冲突解决方式闭散列开散列 模拟实现哈希表的改造 哈希应用位图概念实现 布隆过滤器提出概念 unordered系列关联式容器 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&…...

Spring MVC 的调用(12)

目录 SpringMVC流程 源码分析 第一步:用户发起请求到前端控制器&#xff08;DispatcherServlet&#xff09; 第二步&#xff1a;前端控制器请求处理器映射器&#xff08;HandlerMappering&#xff09;去查找处理器&#xff08;Handle&#xff09;&#xff1a;通过xml配置或者…...

死磕内存篇 --- JAVA进程和linux内存间的大小关系

运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] args) { System.out.println("sleep .."); try { Thread.sleep(10000000); } catch (InterruptedException e) { e.printStackTrace(); } } } java -…...

信号完整性分析:关于传输线的三十个问题解答(三)

21.FR4 中 50 欧姆传输线的单位长度电感是多少&#xff1f;如果阻抗加倍怎么办&#xff1f;&#xff08;What is the inductance per length of a 50-Ohm transmission line in FR4? What if the impedance doubles?&#xff09; FR4 中的所有 50 欧姆传输线的单位长度电感约…...

Java基础:Stream流常用方法

获取Stream流的方式 java.util.stream.Stream 是Java 8新加入的流接口。&#xff08;并不是一个函数式接口&#xff09; 获取一个流非常简单&#xff0c;有以下几种常用的方式&#xff1a; 所有 Collection 集合都可通过 stream 默认方法获取流&#xff08;顺序流&#xff09;…...

ImageNet使用方法(细节)自用!

学习记录&#xff0c;自用。 1. 下载数据集 点击以下链接下载种子文件&#xff0c;然后使用迅雷进行下载&#xff0c;仅下载勾选的文件即可。 https://hyper.ai/datasets/4889/c107755f6de25ba43c190f37dd0168dbd1c0877e 2. 解压 找到下载好的ILSVRC2012_img_train.tar 和…...

C/C++外观模式解析:简化复杂子系统的高效方法

C外观模式揭秘&#xff1a;简化复杂子系统的高效方法 引言设计模式的重要性外观模式简介与应用场景外观模式在现代软件设计中的地位与价值 外观模式基本概念外观模式的定义与核心思想提供简单接口隐藏复杂子系统设计原则与外观模式的关系外观模式实现外观模式的UML图 外观模式的…...

追梦之旅【数据结构篇】——详解小白如何使用C语言实现堆数据结构

详解小白如何使用C语言实现堆数据结构 “痛”撕堆排序~&#x1f60e; 前言&#x1f64c;什么是堆&#xff1f;堆的概念及结构 堆的性质&#xff1a;堆的实现堆向下调整算法画图分析&#xff1a;堆向下调整算法源代码分享&#xff1a;向下调整建小堆向下调整建大堆 堆向上调整算…...

cocoscreator性能优化4-Sprite颜色数据去除

前言 Sprite是游戏内容的一个基本组成元素&#xff0c;包括ui、道具、立绘等各种地方都会用到。大部分情况下美术会帮我们调好图片颜色&#xff0c;我们只要把图片直接放到游戏里就行了。Sprite默认的渲染顶点数据中包含了颜色数据&#xff0c;由于我们并不需要去修改颜色&…...

系统接口幂等性设计探究

前言&#xff1a; 刚开始工作的时候写了一个带UI页面的工具&#xff0c;需要设计登录功能&#xff0c;登录功能也很简单&#xff0c;输入用户名密码点击登录&#xff0c;触发后台查询并比对密码&#xff0c;如果登录成功则返回消息给前端&#xff0c;前端把消息弹出提示一下。…...

C learning_7

目录 1.for循环 1.虽然while循环和for循环本质上都可以实现循环&#xff0c;但是它们在使用方法和场合上还是有一些区别的。 2.while循环中存在循环的三个必须条件&#xff0c;但是由于风格的问题使得三个部分很可能偏离较远&#xff0c;这样 查找修改就不够集中和方便。所以…...

PageRank算法介绍

互联网上有数百亿个网页&#xff0c;可以分为这么几类&#xff1a;不含有用信息的&#xff0c;比如垃圾邮件&#xff1b;少数人比较感兴趣的&#xff0c;但范围不是很广的&#xff0c;比如个人博客、婚礼公告或家庭像册&#xff1b;很多人感兴趣的并且十分有用的&#xff0c;比…...

springboot+vue职称评审管理系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的职称评审管理系统。项目源码请联系风歌&#xff0c;文末附上联系信息 。 目前有各类成品java毕设&#xff0c;需要请看文末联系方式 …...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...