2012-12-10 31 views
31

我遇到了一些Spring bean定義的問題。我有幾個正在由我的main()方法加載的上下文xml文件,並且它們都包含幾乎完全是標籤。當我的主要方法啓動時,我得到這個錯誤從春:註解指定的bean名稱與現有的非兼容bean衝突def

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'converterDAO' for bean class [my.package.InMemoryConverterDaoImpl] conflicts with existing, non-compatible bean definition of same name and class [my.other.package.StaticConverterDAOImpl] 

兩個DAO類註釋是這樣的:

@Repository("converterDAO") 
public class StaticConverterDAOImpl implements ConverterDAO { 
... 
} 

在內存中的道也有@Repository(「converterDAO」 )註釋。在DAO在其他類中引用這樣的:

... 
private @Autowired @Qualifier("converterDAO") ConverterDAO converterDAO; 
... 

我想一個DAO覆蓋另一個的定義,因爲我始終明白這是在第一次使用DI框架的主要原因之一地點。多年來我一直在用xml定義做這件事,從來沒有任何問題。但是組件掃描和註釋的bean定義不是這樣嗎?當Spring說它們不兼容時,Spring意味着什麼?它們實現相同的接口,並且它們被自動裝配到具有該接口類型的字段中。爲什麼他們不兼容?

有人可以提供一種方法讓一個帶註釋的組件掃描的bean重寫另一個嗎?

-Mike

+0

有一些有趣的事情,你第二個代碼片段...請檢查它。 – Yevgeniy

+0

也許你需要分享你的主要方法? –

+0

請添加converterDAO字段的實際聲明。它是一個'ConverterDao'接口還是實現 - 這個問題並不清楚。 –

回答

22

在一個XML文件中,有聲明的序列,你可能會覆蓋以前的定義與較新的一個。當您使用註釋時,在或之前之後沒有的概念。所有的豆都在同一水平。你定義了兩個同名的bean,Spring不知道應該選擇哪一個。

給他們一個不同的名稱(staticConverterDAOinMemoryConverterDAO爲例),創建Spring的XML文件(theConverterDAO例如)在一個別名,並注入器時使用此別名:

@Autowired @Qualifier("theConverterDAO") 
+1

爲什麼沒有之前或之後的概念?我有兩個上下文文件,一個是加載的,然後是下一個。在這方面發生的事情與純XML定義沒有什麼不同。順序僅僅是組件掃描指令遇到的順序。通過第二次掃描產生的豆子覆蓋第一次掃描產生的豆子。我聽到你在說什麼,但我不明白背後的邏輯或技術原因。此外它沒有記錄,這個例外根本沒有意義。當然不是你的錯:-)爲別名的想法點。比回到xml定義更好。 – user1283068

+0

另外,關於的建議,它暗示ConverterDAO的所有不同實現將在加載上下文文件時由Spring檢測和實例化。使用XML,只有最後一個重要的實現將被安裝。這意味着所有ConverterDAO實現的所有自動裝配依賴都必須存在,即使只有一個會被使用。 – user1283068

+0

任何避免與jar檔案的bean名稱衝突的策略? – Stephane

19

我有一個類似的問題,在一個項目中有兩個jar庫(app1和app2)。 bean「BeanName」在app1中定義,並在app2中擴展,並且使用相同的名稱重新定義bean。

在APP1:

package com.foo.app1.pkg1; 

@Component("BeanName") 
public class Class1 { ... } 

在APP 2:

package com.foo.app2.pkg2; 

@Component("BeanName") 
public class Class2 extends Class1 { ... } 

這導致ApplicationContext中裝載ConflictingBeanDefinitionException例外,由於同一組件bean的名字。

爲了解決這個問題,在Spring的配置文件applicationContext.xml:

<context:component-scan base-package="com.foo.app2.pkg2"/> 
<context:component-scan base-package="com.foo.app1.pkg1"> 
    <context:exclude-filter type="assignable" expression="com.foo.app1.pkg1.Class1"/> 
</context:component-scan> 

所以Class1的被排除自動組件掃描並分配給豆,避免名稱衝突。

12

我使用@RestController與Spring 4.x有類似的問題。兩種不同的封裝必須具有相同名稱的類...

package com.x.catalog 

@RestController 
public class TextureController { 
... 

package com.x.cms 
@RestController 
public class TextureController { 
... 

的修復很容易...

package com.x.catalog 

@RestController("CatalogTextureController") 
public class TextureController { 
... 

package com.x.cms 
@RestController("CMSTextureController") 
public class TextureController { 
... 

這個問題似乎是註釋被自動連接,並通過採取類名默認。在@RestController批註中給它一個明確的名稱可以讓你保留類名。

+1

謝謝,像魅力一樣工作。 – Azim

相關問題