2012-11-08 86 views
6

我一直在使用Spring 3.1's bean definition profiles和嵌套的bean進行試驗。我希望能夠根據活動配置文件定義不同的bean。考慮了簡化例如重下,使得我的Spring上下文包含有類似Spring 3.1使用bean定義配置文件的bean可見性

<bean id="say" class="test.Say" p:hello-ref="hello"/> 

<beans profile="prod"> 
    <bean id="hello" class="test.Hello" p:subject="Production!"/> 
</beans> 

<beans profile="dev"> 
    <bean id="hello" class="test.Hello" p:subject="Development!"/> 
</beans> 

我收到以下錯誤:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'say' defined in class path resource [applicationContext.xml]: Cannot resolve reference to bean 'hello' while setting bean property 'hello'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'hello' is defined at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360) aJava Result: 1

我期待的是,你好豆將被定義根據主動Maven配置文件(在我的情況下,proddev)。我開始認爲Spring活動配置文件(spring.profiles.active)可能與Maven配置文件完全無關。

難道有人請解釋我要去哪裏嗎? (甚至可以使用配置文件?)。

回答

12

I was expecting that the hello bean would be defined according to the active Maven profile (in my case prod or dev). I'm starting to think that the Spring active profiles (spring.profiles.active) may be completely unrelated to Maven profiles.

這是真的,它們是無關的。

這裏是你如何解決這個問題:

確保您在src/main/webapp/WEB-INF/文件夾中有web.xml有以下背景設定:

<context-param> 
    <param-name>spring.profile.active</param-name> 
    <param-value>${profileName}</param-value> 
</context-param> 

並確保該maven-war-plugin已過濾轉身對於web.xml

<plugin> 
    <artifactId>maven-war-plugin</artifactId> 
    <version>2.3</version> 
    <configuration> 
     <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors> 
    </configuration> 
</plugin> 

然後最後在您的配置文件中:

<profiles> 
    <profile> 
     <id>dev</id> 
     <properties> 
      <profileName>dev</profileName> 
     </properties> 
    </profile> 
    <profile> 
     <id>prod</id> 
     <properties> 
      <profileName>prod</profileName> 
     </properties> 
    </profile> 
</profiles> 

你也可以在正常的屬性部分添加一個默認值:

<properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <profileName>dev</profileName> 
</properties> 

所以,如果你沒有-P選項運行dev春天配置文件將被使用。

運行時mvn packageweb.xml將具有正確的值spring.profile.active

+0

感謝maba,有沒有一種很好的方式來使用web應用程序之外的spring.profiles.active?例如對於單元測試 –

+1

如果使用彈簧測試,可以使用\ @ActiveProfiles註釋以及其他標準彈簧測試註釋(\ @ContextConfiguration等)。我通常使用它來針對不同的環境進行數據庫測試。在「測試」maven目標期間,我針對derby運行了一個針對derby的攻擊,併爲運行「集成測試」maven目標的oracle提供了另一套攻擊。我創建了抽象類來定義測試和\ @ContextConfiguration,並對其進行擴展,並使用@ActiveProfiles將其轉化爲單元或集成測試。 – Matt

+0

謝謝,我被這個案子困住了,你救了我:D –

2

感謝maba(我的答案我會接受),我開始以不同的方式思考這個問題。

我已經修改了「說」因爲它需要延遲初始化,因爲在最初遇到它嵌套豆環境還不存在。因此,新版本增加了一個新的bean,並改變了「說」定義,使得它現在的樣子:

<bean class="test.InitProfile" p:profiles="dev"/> 

<bean id="say" class="test.Say" lazy-init="true" p:hello-ref="hello"/> 

新InitProfile bean是一個的InitializingBean負責建立有效的配置文件。

它包含:

package test; 

import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.InitializingBean; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 
import org.springframework.context.ConfigurableApplicationContext; 
import org.springframework.util.StringUtils; 

public class InitProfile implements InitializingBean, ApplicationContextAware { 

    private ConfigurableApplicationContext ctx; 
    private String[] profiles; 

    public void setApplicationContext(ApplicationContext ac) throws BeansException { 
     ctx = (ConfigurableApplicationContext) ac; 
    } 

    public void setProfiles(String inprofiles) { 
     if (inprofiles.contains(",")) { 
      profiles = StringUtils.split(inprofiles, ","); 
     } else { 
      profiles = new String[]{inprofiles}; 
     } 
    } 

    public void afterPropertiesSet() throws Exception { 
     String[] activeProfiles = ctx.getEnvironment().getActiveProfiles(); 
     if (profiles != null && activeProfiles.length == 0) { 
      ctx.getEnvironment().setActiveProfiles(profiles); 
      ctx.refresh(); 
     } 
    } 
} 

使用這種方法的優點是能夠使用classpath屬性文件來設置活動彈性曲線的附加優勢(這個可以根據我的積極Maven的配置不同的)。我也喜歡這種方法,因爲我可以將它用於Web應用程序和命令行應用程序。