2010-01-29 121 views
29

我正在使用Spring將JMS連接工廠注入到我的Java應用程序中。由於這個工廠只在生產環境中需要,而不是在我開發的時候,所以我把bean定義放到了一個單獨的XML中,我將其包含到我的主applicationContext.xml中。在生產環境中,這個額外的文件包含常規的bean定義。在我的本地開發環境中,我希望這個bean爲null。當Spring遇到一個它不知道的引用ID時,嘗試簡單地刪除bean定義,顯然導致了一個錯誤。有意將Spring bean設置爲null

所以我試着創建一個工廠bean,它會簡單地返回null。如果我這樣做,Spring(2.5.x)會抱怨工廠返回null,儘管基於FactoryBean接口的Spring API文檔,我期望這個接口可以工作(請參閱Spring API doc)。

的XML看起來是這樣的:

<bean id="jmsConnectionFactoryFactory" class="de.airlinesim.jms.NullJmsConnectionFactoryFactory" /> 

<bean id="jmsConnectionFactory" factory-bean="jmsConnectionFactoryFactory" factory-method="getObject"/> 

什麼是這樣做的「正確」的方式?

回答

20

factory-bean/factory-methodnull工作,但自定義FactoryBean實現正常工作:

public class NullFactoryBean implements FactoryBean<Void> { 

    public Void getObject() throws Exception { 
     return null; 
    } 

    public Class<? extends Void> getObjectType() { 
     return null; 
    } 

    public boolean isSingleton() { 
     return true; 
    } 
} 
<bean id="jmsConnectionFactory" class = "com.sample.NullFactoryBean" /> 
+6

這是一個開放的功能請求,但一直在那裏坐2年......投票可能會有所幫助:http://jira.springframework.org/browse/SPR-5320 – skaffman

+0

這對我而言並不適用,如果我在'@ Autowired'上下文中使用了這個bean。 –

+0

如果我返回null,我得到BeanCreationException。由於:org.springframework.beans.factory.BeanCreationException:在類路徑資源[XXX.xml]中定義名爲'nullObject'的bean時出錯:factory-bean'NullFactoryBean'返回null – endless

-1

您可以使用特殊的<null> bean元素嗎?例如

<bean class="ExampleBean"> 
<property name="email"><null/></property> 
</bean> 

the doc,部分3.3.2.5

+1

設置最終應用bean的屬性格式時,這可能會工作。但在這一點上,我只提供引用ID「jmsConnectionFactory」,然後引用實際的bean或null(如果可能的話)。 – Lunikon

27

我敢確保Spring不會允許您將null與bean id或別名相關聯。您可以通過將屬性設置爲null來處理此問題。

這裏是你如何做到這在Spring 2.5

<bean class="ExampleBean"> 
    <property name="email"><null/></property> 
</bean> 

在Spring 3.0中,你也應該能夠使用Spring expression language (SpEL);例如

<bean class="ExampleBean"> 
    <property name="email" value="#{ null }"/> 
</bean> 

或任何評估爲null的SpEL表達。

如果您使用的是佔位符配置器,你可以甚至可能做到這一點:

<bean class="ExampleBean"> 
    <property name="email" value="#{ ${some.prop} }`"/> 
</bean> 

其中some.prop可以在屬性文件中被定義爲:

some.prop=null 

some.prop=some.bean.id 

請注意,我還沒有使用SpEL(還),所以可能有問題與索姆e以上...

+1

我更喜歡這個解決方案;它不需要創建自定義工廠bean – Richard

4

上面提到的一些問題,axtact的答案在Autowiring中不起作用,其中Spring將依賴getObjectType()方法中的正確信息。所以,你可能最終喜歡的錯誤:

 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [xxxxxxxxxxxxx] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=yyyyyyyyyyyyyyyy)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:920) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotatio 

所以這裏有一個小的變化,這包括允許用戶迫使objectype施工。使用屬性而不是構造函數arg不起作用,因爲Spring並未在此上下文中完全初始化bean。

public class NullFactoryBean implements FactoryBean { 
    private final Class<?> objectType; 

    public NullFactoryBean(Class<?> objectType) { 
     this.objectType = objectType; 
    } 

    @Override 
    public Object getObject() throws Exception { 
     return null; 
    } 

    @Override 
    public Class<?> getObjectType() { 
     return objectType; 
    } 

    @Override 
    public boolean isSingleton() { 
     return false; 
    } 
} 
5

對於沒有人來對這個問題,要記住,簡單地設置@Autowired註解可選會做的伎倆(即春將離開參考空,如果沒有符合條件的bean被發現)。

,你將不得不這樣做到處豆
@Autowired(required = false) 
private SomeClass someBean 

注意被引用,這可能比上述創建一個空的工廠更大的麻煩。

0

在測試空豆類也可注入這樣的:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = NullTest.class) 
@Configuration 
public class NullTest { 

    @Bean(name = "em") 
    public IEntityManager em() { return null; } 
    @Bean 
    public PlatformTransactionManager tm() { return null; } 

    @Resource 
    private SomeBean someBean; // this would get em and tm fields autowired to nulls