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

一、前言

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

  • 采用springAOP的方式实现事务

  • 制作过程可以参考:

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

二、制作starter

1、完整结构图

用spring-boot-starter实现事务的统一配置_第1张图片

2、引用模块

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

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

  • pom.xml

<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.0modelVersion>

    <groupId>com.tuwergroupId>
    <artifactId>tuwer-transaction-spring-boot-starterartifactId>
    <version>1.0-SNAPSHOTversion>
    <description>事务starterdescription>

    <properties>
        <maven.compiler.source>8maven.compiler.source>
        <maven.compiler.target>8maven.compiler.target>
        
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    properties>
    <dependencies>
        
        <dependency>
            <groupId>com.tuwergroupId>
            <artifactId>tuwer-transaction-spring-boot-starter-autoconfigureartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>
    dependencies>
project>

3、自动配置模块

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

1> pom.xml

使用jdbc的事务管理器


<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.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.6.7version>
    parent>
    <modelVersion>4.0.0modelVersion>

    <groupId>com.tuwergroupId>
    <artifactId>tuwer-transaction-spring-boot-starter-autoconfigureartifactId>
    <version>1.0-SNAPSHOTversion>
    <description>事务starter自动配置模块description>

    <properties>
        <maven.compiler.source>8maven.compiler.source>
        <maven.compiler.target>8maven.compiler.target>
        
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    properties>
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-aopartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-jdbcartifactId>
        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;

/**
 * 

事务属性类

* * @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;

/**
 * 

事务自动配置类

* * @author 土味儿 * Date 2023/4/17 * @version 1.0 */
@Aspect @Configuration @EnableConfigurationProperties(TransactionProperty.class) public class TuwerTransactionAutoConfiguration { /** * 注入 TransactionProperty 属性配置类 */ @Resource private TransactionProperty transactionProperty; /** * 注入事务管理器 */ @Resource private TransactionManager transactionManager; /** * 定义事务增强 * * @return */ @Bean public 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 */ @Bean public 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依赖


<dependency>
	<groupId>com.tuwergroupId>
	<artifactId>tuwer-transaction-spring-boot-starterartifactId>
	<version>1.0-SNAPSHOTversion>
dependency>

2、配置切入点

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

至此,事务配置就OK了!

你可能感兴趣的:(#,SpringBoot,#,SpringCloud,Spring,java,spring,spring,boot)