7

I have been experimenting with using Spring 3.1's bean definition profiles and nested beans. I had hoped that I could define different beans depending on the active profile. Consider the following heavily over simplified example such that my Spring context contains something like

<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>

I get the following error:

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

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.

Could somebody please explain where I am going wrong? (Is this even possible using profiles?).

4

2 に答える 2

12

アクティブな Maven プロファイル (私の場合は prod または dev) に従って hello Bean が定義されることを期待していました。Spring のアクティブ プロファイル (spring.profiles.active) は、Maven プロファイルとはまったく関係がないのではないかと考え始めています。

それは本当です、それらは無関係です。

これを修正する方法は次のとおりです。

フォルダにある に次のコンテキスト設定がweb.xmlあることを確認してください。src/main/webapp/WEB-INF/

<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 packageするweb.xmlと、 の正しい値が得られますspring.profile.active

于 2012-11-08T12:22:45.350 に答える
2

マバのおかげで(私はその答えを受け入れます)、私はこれについて別の方法で考え始めました.

最初に遭遇したときにネストされた Bean コンテキストがまだ存在しないため、遅延初期化する必要があるため、Beanを「言う」ように変更しました。したがって、新しいバージョンでは新しい Bean が追加され、「say」定義が次のように変更されます。

<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();
        }
    }
}

このアプローチを使用すると、クラスパス プロパティ ファイルを使用してアクティブなスプリング プロファイルを設定できるという利点が追加されます (これは、アクティブな Maven プロファイルによって異なります)。Web アプリケーションとコマンド ライン アプリケーションの両方に使用できるため、このアプローチも気に入っています。

于 2012-11-08T14:01:36.883 に答える