首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 實戰避坑指南:18 類常見錯誤總結與解決方案

     編輯:Java 相關知識

前言:從異常堆疊中讀懂 Spring

Spring 開發中,異常堆疊往往比文檔更誠實。本文彙總 18 類高頻錯誤,按依賴注入、配置元數據、類型轉換、AOP 代理、事務整合五大維度分類,附帶根因分析與修復代碼,助你快速定位、徹底解決。


一、依賴注入缺失類

錯誤 1:NotWritablePropertyException —— 缺少 Setter 方法

Error creating bean with name 'helloServiceImpl'... 
Invalid property 'helloDao'... Bean property 'helloDao' is not writable or has an invalid setter method.

根因:Service 類聲明了 private HelloDao helloDao; 但未提供 setHelloDao()。Spring 基於 Setter 注入,屬性必須可寫。

修復:補全 Setter:

public void setHelloDao(HelloDao helloDao) {
    this.helloDao = helloDao;
}

錯誤 2:XML 屬性值缺少引號

org.xml.sax.SAXParseException: Open quote is expected for attribute "scope"

根因:<bean scope=prototype> 缺少雙引號。XML 規範要求屬性值必須用引號包裹。

修復:<bean scope="prototype">

錯誤 3:Java 代碼中 Bean ID 拼寫錯誤

No bean named 'helloServiceImp' is defined

根因:context.getBean("helloServiceImp") 少寫一個 "l",配置文件中為 helloServiceImpl。

修復:IDE 重構重命名、或使用常量定義 Bean ID。

錯誤 4:配置文件間引用 ID 不一致

Cannot resolve reference to bean 'helloDaoImp' while setting bean property 'helloDao'

根因:spring-service.xml 引用 ref="helloDaoImp",但 spring-dao.xml 定義為 id="helloDaoImpl"。

修復:統一 ID 命名規範,跨文件引用時複製粘貼 ID。

錯誤 5:類全限定名寫錯(包路徑錯誤)

Cannot find class [www.csdn.spring.dao.imp.HelloDaoImpl]... ClassNotFoundException

根因:配置 class="www.csdn.spring.dao.imp.HelloDaoImpl",實際類在 dao.impl 包下。

修復:核對 class 屬性與實際類路徑一致。


二、構造器注入與類型匹配類

錯誤 6:構造器參數類型不匹配(基本類型 vs 包裝類型)

UnsatisfiedDependencyException: Ambiguous constructor argument types - did you specify the correct bean references?

根因:類屬性 private double salary;(基本類型),配置卻用 <constructor-arg type="java.lang.Double">(包裝類型)。構造器類型匹配不支援自動拆裝箱。

修復:類型完全一致:

<constructor-arg type="double" value="5000.00"/>  // 基本類型
或
<constructor-arg type="java.lang.Double" value="5000.00"/>  // 類屬性改為 Double

錯誤 7:注入 null 值語法錯誤

ConversionNotSupportedException: Cannot convert value of type [java.lang.String] to required type [Member]

根因:<property name="member" value="null"/> 將字符串 "null" 注入對象屬性。

修復:使用專用 <null/> 標籤:

<property name="member"><null/></property>

三、自動裝配衝突類

錯誤 8/9:byType/constructor 自動裝配發現多個候選 Bean

NoUniqueBeanDefinitionException: expected single matching bean but found 2: deptBean,deptBean1

根因:容器中存在多個同類型 Bean(DeptBean),自動裝配無法確定唯一候選者。

修復方案:

  • 改用 byName 或顯式 ref 引用
  • 標註 @Primary(註解配置)或 primary="true"(XML)
  • 縮小組件掃描範圍

四、集合注入與解析類

錯誤 10:<property> 缺少 ref 或 value

Configuration problem: <property> element for property 'users' must specify a ref or value

根因:集合屬性配置中註釋掉了所有注入方式(<list>、<array>、<util:list> 均被註釋),導致屬性無值。

修復:保留一種集合注入配置並取消註釋。


五、AOP 代理與切面類

錯誤 11:JDK 動態代理 vs CGLIB 代理混用導致類型轉換失敗

Bean named 'proxyFactoryBean' must be of type [SayServiceImpls], but was actually of type [$Proxy4]

根因:JDK 代理生成接口代理(返回接口類型),CGLIB 生成子類代理(返回類類型)。配置中目標類實現接口卻強制用 CGLIB,或混合使用導致類型不匹配。

修復:

  • 統一代理策略:<aop:config proxy-target-class="true"> 強制 CGLIB
  • 目標類不實現接口時才用 CGLIB
  • 引用類型改為接口類型

錯誤 12:proxyInterfaces 設置為實現類而非接口

IllegalArgumentException: [SayServiceImpl] is not an interface

修復:<value>www.csdn.spring.proxy.advice.SayService</value>(接口全限定名)

錯誤 13:通知類未實現正確接口

UnknownAdviceTypeException: Advice object [AuditableImpl] is neither a supported subinterface of Advice nor an Advisor

根因:自定義通知類(如前置通知)未實現 MethodBeforeAdvice 等標準接口。

標準通知接口對照表:

通知類型實現接口
前置通知MethodBeforeAdvice
後置通知AfterReturningAdvice
環繞通知MethodInterceptor
異常通知ThrowsAdvice
引入通知DelegatingIntroductionInterceptor

錯誤 14:ClassCastException: $ProxyXX cannot be cast to ...

常見原因:

  1. JDK/CGLIB 代理混淆(同上)
  2. @AspectJ 引入通知缺少 @Aspect 註解
  3. 引入通知的接口/實現類包路徑錯誤

修復:檢查 <aop:aspectj-autoproxy proxy-target-class="true"/>、確認 @Aspect 註解、核對類路徑。

錯誤 15:<aop:aspect> 缺少 ref 屬性

Configuration problem: <aspect> tag needs aspect bean reference via 'ref' attribute

修復:<aop:aspect ref="adviceService">


六、數據庫與 ORM 整合類

錯誤 16:NamedParameterJdbcTemplate Bean 定義循環引用

Could not resolve matching constructor... specify index/type/name arguments

根因:<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/> 自己引用自己。

修復:正確注入到 DAO:

<bean id="deptDaoImpl" class="...">
    <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/>
</bean>

錯誤 17:Hibernate 方言未配置導致無法獲取連接

HibernateException: 'hibernate.dialect' must be set when no Connection available

根因:數據源配置錯誤(驅動類名、URL、用戶名密碼)導致無法獲取連接,Hibernate 無法自動檢測方言。

修復:

  • 核對 jdbc.properties 中驅動類名拼寫:oracle.jdbc.driver.OracleDriver
  • 顯式配置方言:<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
  • 屬性佔位符一致性:${hibernate.driverClassName} vs ${jdbc.driverClassName}

錯誤 18:HQL 語法錯誤

java.lang.IllegalArgumentException: node to traverse cannot be null!

常見 HQL 寫法錯誤:

  • from 寫成 form
  • set a=1 and b=2 應為 set a=1, b=2(逗號分隔)
  • 關鍵字大小寫、實體類名與表名映射錯誤

總結:錯誤診斷三步法

  1. 看 Caused by:定位最底層根因異常類名
  2. 對照配置:XML/註解與 Java 類屬性、類名、包路徑逐行核對
  3. 查文檔/源碼:Spring 異常信息通常已包含修復提示(如 "specify index/type/name arguments")

核心原則:拼寫一致性 > 複雜邏輯。絕大多數 Spring 錯誤源於 ID 拼寫、類型不匹配、配置缺失等基礎疏漏。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved