經典 Spring 錯誤:No bean named 'PubCommonDAO' is defined,堆疊跟蹤指向 LogViewerService.findCodes() → LogViewerController.index()。明明 XML 配了 Bean,為什麼容器找不到?本文給出三步排查法。
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'PubCommonDAO' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(...)
at org.service.LogViewerService.findCodes(LogViewerService.java:20)
at org.controller.LogViewerController.index(LogViewerController.java:37)
<!-- 典型錯誤:id 拼寫不一致 -->
<bean id="pubCommonDAO" class="org.dao.PubCommonDAOImpl" /> <!-- 小寫 p -->
<!-- Java 代碼注入 -->
@Resource(name = "PubCommonDAO") <!-- 大寫 P -->
private PubCommonDAO pubCommonDAO;
id/name 大小寫完全匹配。class 全限定名正確、無拼寫錯誤。<import resource="..."/> 或 <context:component-scan> 掃描到。target/classes/org/dao/PubCommonDAOImpl.class 是否存在?Build → Rebuild Project,清理緩存。pom.xml 依賴範圍:<scope>provided</scope> 會導致打包無 Class。ContextLoaderListener (父) 載入 Service/Dao/DAO → DispatcherServlet (子) 載入 Controller。PubCommonDAO 在子容器 XML 配置,Service(父容器)無法引用 → 移至父容器配置文件(如 applicationContext.xml)。<bean lazy-init="true"> 導致首次注入失敗?改為 lazy-init="false"。// 在 Controller 或測試類注入 ApplicationContext
@Autowired ApplicationContext ctx;
public void debugBeans() {
String[] names = ctx.getBeanDefinitionNames();
Arrays.stream(names)
.filter(n -> n.contains("PubCommonDAO") || n.contains("pubCommonDAO"))
.forEach(System.out::println);
// 直接嘗試獲取
try {
Object bean = ctx.getBean("PubCommonDAO");
System.out.println("Found: " + bean.getClass());
} catch (Exception e) {
System.out.println("Not found: " + e.getMessage());
}
}
| 現象 | 真相 | 修正 |
|---|---|---|
| XML 寫了但報錯 | XML 未被載入(路徑錯/未 import) | 檢查 web.xml contextConfigLocation |
| 類存在但報錯 | 編譯輸出目錄無 .class 文件 | Rebuild / 清理 target 重新編譯 |
| 父容器 Bean 子容器不可見 | 雙容器隔離,反向不可見 | DAO/Service 放父容器,Controller 放子容器 |
| @Autowired 報錯 | 多實現類無 @Primary/@Qualifier | 指定 @Qualifier("pubCommonDAO") |
遇到 NoSuchBeanDefinitionException,別慌:對照 XML 與 Java 拼寫 → 確認 Class 產出 → 搞清容器層級,三步定位 99% 原因。