用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实现事务的统一配置
一、前言 微服务架构下,多个微服务都需要事务操作,如果在每个微服务下都从头配置事务,将非常繁锁。事务配置具有高度的一致性,可以抽取出来,制作starter,在需要配置事务的服务中引入starter依赖即可。 采用…...
C语言中fopen的详细用法
fopen是C语言中用于打开文件的函数,其原型为: FILE *fopen(const char *filename, const char *mode); 其中,filename是要打开的文件名,mode是打开文件的模式。fopen函数返回一个指向FILE类型的指针,该指针指向打开的…...
C语言——学生信息管理系统(数组)
文章目录 一、前言二、目的三、框架1.菜单1.1主菜单1.2子菜单 2.流程图2.1总流程图2.2开始流程图2.3增加学生信息流程图2.4.删除学生信息流程图2.5修改学生信息流程图2.6查询学生信息流程图2.7对学生信息排序流程图 3.思路 四、代码五、演示视频 一、前言 因为最近是在赶进度总…...
【C语言】基础语法1:变量和数据类型
下一篇:运算符和表达式 ❤️🔥前情提要❤️🔥 欢迎来到C语言基本语法教程 在本专栏结束后会将所有内容整理成思维导图(结束换链接)并免费提供给大家学习,希望大家纠错指正。本专栏将以基础出发…...
linux安装和使用jekins
Jenkins详细安装配置部署--超详细_jenkins安装部署_宝贝富贵猪的博客-CSDN博客 1.安装JDK 2.获取安装包 下载页面:https://jenkins.io/zh/download/ 或者Index of /jenkins/redhat/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 3.安装Jenkins sud…...
驼峰式匹配
问题: 如果我们可以将小写字母插入模式串 pattern 得到待查询项 query,那么待查询项与给定模式串匹配。(我们可以在任何位置插入每个字符,也可以插入 0 个字符。) 给定待查询列表 queries,和模式串 patte…...
第三十七章 立方体贴图总结
立方体贴图:将多个纹理组合起来映射到一张纹理上的一种纹理类型。 一个立方体贴图时包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面,相当于是一个有纹理的立方体。 创建立方体贴图: 首先需要生成一个纹理,将其绑定到纹理目标上,再做其他纹理操作。补充:绑定到…...
哈希(C++)
哈希 unordered系列关联式容器unordered_map介绍 底层结构哈希概念哈希冲突哈希函数哈希冲突解决方式闭散列开散列 模拟实现哈希表的改造 哈希应用位图概念实现 布隆过滤器提出概念 unordered系列关联式容器 在C98中,STL提供了底层为红黑树结构的一系列关联式容器&…...
Spring MVC 的调用(12)
目录 SpringMVC流程 源码分析 第一步:用户发起请求到前端控制器(DispatcherServlet) 第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过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 欧姆传输线的单位长度电感是多少?如果阻抗加倍怎么办?(What is the inductance per length of a 50-Ohm transmission line in FR4? What if the impedance doubles?) FR4 中的所有 50 欧姆传输线的单位长度电感约…...
Java基础:Stream流常用方法
获取Stream流的方式 java.util.stream.Stream 是Java 8新加入的流接口。(并不是一个函数式接口) 获取一个流非常简单,有以下几种常用的方式: 所有 Collection 集合都可通过 stream 默认方法获取流(顺序流)…...
ImageNet使用方法(细节)自用!
学习记录,自用。 1. 下载数据集 点击以下链接下载种子文件,然后使用迅雷进行下载,仅下载勾选的文件即可。 https://hyper.ai/datasets/4889/c107755f6de25ba43c190f37dd0168dbd1c0877e 2. 解压 找到下载好的ILSVRC2012_img_train.tar 和…...
C/C++外观模式解析:简化复杂子系统的高效方法
C外观模式揭秘:简化复杂子系统的高效方法 引言设计模式的重要性外观模式简介与应用场景外观模式在现代软件设计中的地位与价值 外观模式基本概念外观模式的定义与核心思想提供简单接口隐藏复杂子系统设计原则与外观模式的关系外观模式实现外观模式的UML图 外观模式的…...
追梦之旅【数据结构篇】——详解小白如何使用C语言实现堆数据结构
详解小白如何使用C语言实现堆数据结构 “痛”撕堆排序~😎 前言🙌什么是堆?堆的概念及结构 堆的性质:堆的实现堆向下调整算法画图分析:堆向下调整算法源代码分享:向下调整建小堆向下调整建大堆 堆向上调整算…...
cocoscreator性能优化4-Sprite颜色数据去除
前言 Sprite是游戏内容的一个基本组成元素,包括ui、道具、立绘等各种地方都会用到。大部分情况下美术会帮我们调好图片颜色,我们只要把图片直接放到游戏里就行了。Sprite默认的渲染顶点数据中包含了颜色数据,由于我们并不需要去修改颜色&…...
系统接口幂等性设计探究
前言: 刚开始工作的时候写了一个带UI页面的工具,需要设计登录功能,登录功能也很简单,输入用户名密码点击登录,触发后台查询并比对密码,如果登录成功则返回消息给前端,前端把消息弹出提示一下。…...
C learning_7
目录 1.for循环 1.虽然while循环和for循环本质上都可以实现循环,但是它们在使用方法和场合上还是有一些区别的。 2.while循环中存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样 查找修改就不够集中和方便。所以…...
PageRank算法介绍
互联网上有数百亿个网页,可以分为这么几类:不含有用信息的,比如垃圾邮件;少数人比较感兴趣的,但范围不是很广的,比如个人博客、婚礼公告或家庭像册;很多人感兴趣的并且十分有用的,比…...
springboot+vue职称评审管理系统(源码+文档)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的职称评审管理系统。项目源码请联系风歌,文末附上联系信息 。 目前有各类成品java毕设,需要请看文末联系方式 …...
个人自动化技能库构建指南:从Python脚本到Cron定时任务
1. 项目概述:一个为“摸鱼”场景设计的自动化技能库最近在GitHub上看到一个挺有意思的项目,叫my-copaw-skill。光看这个名字,就透着一股子“打工人”的幽默感——“copaw”这个词,我琢磨着应该是“copilot”(副驾驶/助…...
CentOS8实战:ZeroTier构建安全异地虚拟局域网
1. 为什么选择ZeroTier替代传统内网穿透方案 最近在帮朋友搭建远程办公环境时,遇到了一个典型问题:分布在三个不同物理位置的服务器需要像在同一个办公室内网那样互相访问。最初考虑使用FRP方案,但实测下来发现几个痛点:首先是带宽…...
Swagger2Word终极指南:3种方法实现API文档自动化转换
Swagger2Word终极指南:3种方法实现API文档自动化转换 【免费下载链接】swagger2word 项目地址: https://gitcode.com/gh_mirrors/swa/swagger2word 还在为手动编写API文档而烦恼吗?Swagger2Word为你提供了一站式自动化解决方案,将Swa…...
Halcon深度学习工具(DLT)安装与中文环境配置实战
1. Halcon DLT安装前的准备工作 第一次接触Halcon深度学习工具(DLT)时,我完全被各种专业术语搞晕了。后来才发现,只要做好前期准备,安装过程其实比想象中简单得多。首先需要确认的是你的Windows系统版本,DLT目前支持Windows 10和1…...
技能工程化框架:从标准化定义到编排实战
1. 项目概述:从“技能”到“智能”的工程化桥梁在当今的软件开发领域,尤其是涉及复杂交互和自动化流程的场景,我们常常会听到“技能”这个词。它听起来很抽象,但如果你拆解过任何一款智能助手、自动化机器人或者一个大型的业务流程…...
Arm CoreLink PCK-600电源管理架构与寄存器编程详解
1. Arm CoreLink PCK-600电源控制架构解析在嵌入式系统设计中,电源管理单元(PMU)是实现高效能耗控制的核心组件。Arm CoreLink PCK-600作为业界领先的电源控制解决方案,其架构设计体现了现代SoC电源管理的先进理念。PCK-600系列采…...
fold命令行工具:高效文本数据聚合与分析的瑞士军刀
1. 项目概述:一个为“折叠”而生的高效工具 最近在折腾一些数据处理和文件整理的工作流时,我一直在寻找一个能让我“折叠”起来思考的工具。我说的“折叠”,不是物理上的,而是逻辑上的——把复杂的、多维度的信息,按照…...
轻量级服务器监控面板:从原理到部署实战
1. 项目概述:一个开源监控面板的诞生最近在折腾服务器和容器化应用,发现一个挺普遍的需求:当你手头有几台服务器,上面跑着几个Docker容器,或者一些自己写的服务,你总想知道它们现在“活”得怎么样。CPU是不…...
数据流编排与异步任务调度中间件kelivo部署与实战指南
1. 项目概述与核心价值最近在折腾一个挺有意思的项目,叫“Chevey339/kelivo”。乍一看这个标题,可能有点摸不着头脑,它不像那些直接告诉你“XX管理系统”或“XX工具库”的项目名那么直白。但恰恰是这种看似神秘的命名,背后往往隐藏…...
Kubernetes上Jenkins全栈部署:动态Agent与生产环境调优指南
1. 项目概述:一个面向Kubernetes的Jenkins全栈部署方案在容器化和云原生技术成为主流的今天,如何高效、稳定地部署和管理持续集成/持续交付(CI/CD)流水线,是每个开发团队和运维工程师必须面对的课题。传统的单体Jenkin…...
