StackTraces
Spring Boot已驗證

Spring Boot 報 No bean named transactionManager

@debug_master27 天前更新閱讀 6 min00

@Transactional 預設按名稱 transactionManager 查找事務管理器 Bean。只配了數據源卻把事務自動設定 exclude 掉、或自動裝配根本沒觸發,就會拋 NoSuchBeanDefinitionException: No bean named 'transactionManager' available——這是裝配期就爆掉的硬報錯,不是靜默失效。

Issue & Env(案發現場與環境)

  • JDK 版本:OpenJDK 17 / 21
  • Spring Boot 版本:2.7.x / 3.x
  • 依賴場景:使用 MyBatis / JDBC,或自定義數據源設定類但未註冊配套事務管理器。
  • 觸發背景:應用啟動一切正常,但在接收到第一個進入 @Transactional 標註方法的業務請求時,系統直接拋出例外並中斷請求處理。

Spring Boot 的聲明式事務依賴一個 PlatformTransactionManager Bean。絕大多數項目不需要手動定義它,因為 Boot 提供了自動裝配:

  • 用 JDBC / MyBatis 時,DataSourceTransactionManagerAutoConfiguration 自動註冊 DataSourceTransactionManager;
  • 用 JPA 時,JpaTransactionManagerAutoConfiguration 自動註冊 JpaTransactionManager。

這些自動裝配都有條件:類路徑上要有對應依賴、容器裡有 DataSource Bean、且沒有被 exclude。一旦條件不滿足或被手動排除,事務管理器就不會被註冊。

StackTrace(堆疊日誌)

org.springframework.beans.factory.NoSuchBeanDefinitionException:
  No bean named 'transactionManager' available:
    expected at least 1 bean which qualifies as autowire candidate.
    Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1324)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:507)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

關鍵特徵:錯誤不在啟動階段,而是第一個事務方法調用時爆發,且例外棧裡一定有 TransactionAspectSupport.determineTransactionManager。

Reproduce(復現程式碼)

啟動類或設定類中顯式排除了事務自動裝配類,或只聲明瞭數據源未聲明事務管理器:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;

// 复现:人为排除了 DataSourceTransactionManagerAutoConfiguration
@SpringBootApplication(exclude = DataSourceTransactionManagerAutoConfiguration.class)
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

業務 Service 正常使用 @Transactional:

package com.example.demo.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderService {
    @Transactional
    public void createOrder() {
        // 任何数据库操作,进入该方法即刻抛出 NoSuchBeanDefinitionException
    }
}

Root Cause(根因分析)

  1. Spring 事務切面的解析機制:當切面攔截到 @Transactional 方法時,TransactionAspectSupport.determineTransactionManager 會先嚐試通過名稱(預設 transactionManager)獲取 PlatformTransactionManager。若註解上未指定 qualifier,Spring 會從容器中尋找唯一的事務管理器。
  2. 自動裝配失效的三大誘因:
    • 線索 1:主動 exclude。在 @SpringBootApplication 或設定中誤將 DataSourceTransactionManagerAutoConfiguration.class 加入了 exclude 列表。
    • 線索 2:自定義數據源未註冊配套事務管理器。團隊自定義了多數據源或公共 DataConfig,顯式聲明瞭 DataSource Bean,使 Spring Boot 預設的自動化數據源與事務管理器設定全面退讓,但開發者未手動補上 @Bean PlatformTransactionManager。
    • 線索 3:缺少依賴。僅引入了第三方連接池但缺少 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa,導致自動裝配條件 ConditionOnClass 無法達成。

可用以下命令快速排查是否存在 exclude 或檢查條件評估報告:

grep -rn "exclude.*TransactionManager\|excludeName.*TransactionManager" src/main/java
java -jar app.jar --debug | grep -A2 "DataSourceTransactionManagerAutoConfiguration"

The Fix(解決方案)

方案 A(推薦):恢復自動裝配,不手動管理

去掉對事務自動設定的 exclude,確保 spring-boot-starter-jdbc(或 spring-boot-starter-data-jpa)在依賴裡,讓 Boot 自動註冊事務管理器:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

方案 B:手動補裝配(多數據源 / 定製場景)

在多數據源或定製設定類中,補齊 PlatformTransactionManager Bean 定義:

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

方案 C:顯式指定事務管理器名稱

如果容器裡有事務管理器但不叫 transactionManager(例如叫 txManager),在 @Transactional 上顯式指定:

@Transactional(transactionManager = "txManager")

References(參考來源)

最後更新於 2026-09-14

這篇幫到你了嗎?

剛解決了一個棘手的報錯?花兩分鐘記錄下來,幫助下一個遇到同樣問題的開發者。

貢獻一條解法