2010-11-06 69 views
2

當我有以下建立其工作完全正常:NoSuchBeanDefinitionException實現一個新的接口

@Service 
public class MyService { 
} 

public class Test { 
    @Autowired 
    MyService service; 
} 

我改變爲MyService實現一個新的接口,這樣

@Service 
public class MyService implements NewInterface { 
} 

沒有什麼特別的這個接口,它只是一個普通的Java接口,沒有任何註釋和2個非常簡單的方法。

現在,Spring不能自動裝配這個bean了,它給出了一個NoSuchBeanDefinitionException。我也試圖在XML中明確地定義它,但它給出了相同的例外。

如果相關,我使用Spring 2.5並使用Maven構建,類Test是一個單元測試類。當我嘗試運行實際的應用程序時,它使用applicationContext.getBean()來獲得此服務,並給出以下例外:java.lang.ClassCastException: $Proxy81 cannot be cast to MyService

我錯過了什麼,該怎麼辦?

回答

3

當你看到一個類名爲$Proxy81的類時,它告訴你Spring已經爲你的一個bean自動生成了一個代理對象,在這個例子中是MyService bean的代理對象。這使用java.lang.reflect.Proxy來生成代理對象。該代理對象將實現與正在代理的類相同的接口,但它不會與目標類本身類型兼容。

現在,如果目標類沒有實現任何接口,那麼Spring將改爲使用CGLIB來生成代理。該代理將是目標類的子類,因此代理對象可以安全地轉換爲目標對象的原始類型。

現在,當在Spring中使用底層代理生成的東西時,你可以經常覆蓋這種行爲,並告訴它總是使用CGLIB代理,但我假設因爲你使用的是@Service,那麼你'也使用<context:component-scan>,在這種情況下,我認爲你必須堅持默認行爲。

不過這不是件壞事。這鼓勵你不要將你的類連接在一起,而是編程到接口。任何與MyService的交互都應該可以通過接口來表達,儘管這個概念在談到單元測試時可能會有些模糊。

+0

感謝您的詳細和明確的解釋。 – Damien 2010-11-06 22:09:52

3

它看起來像通過接口自動裝配,而不是按類名自動裝配。

我只是對接口代碼我的測試:

public class Test { 
    @Autowired 
    NewInterface service; 
} 

此外,檢查this bug,因爲它看起來像你的類是被代理這可能是與你有關的。

+0

謝謝,我接受了更詳細的skaffman答案,但基本上你也是對的。你的代碼片段並不好,因爲這個現有的Test類調用的方法不會通過NewInterface公開(也不應該),所以我需要爲現有的方法創建另一個新的接口。 – Damien 2010-11-06 22:11:16