为AbstractAnnotationConfigDispatcherServletInitializer设置一个可以与@PropertySource一起使用的活动配置文件?

时间:2013-12-16 18:11:11

标签: spring spring-mvc spring-3

我正在使用AbstractAnnotationConfigDispatcherServletInitializer配置我的网络应用程序。我还有一个@Configuration类用于创建一些bean。在本课程中,我使用@PropertySource注释来加载各种设置的属性文件(例如数据库连接详细信息)。

目前,我使用Maven配置文件和Ant任务为我的运行时环境创建正确的属性文件。也就是说,我让Maven在构建时将“prod.properties”或“dev.properties”移动到“application.properties”(该类使用)。我想要做的是使用Spring配置文件来消除这种情况。我希望能够做到以下几点:

@PropertySource( value = "classpath:/application-${spring.profiles.active}.properties")

我还想在不使用任何XML的情况下设置配置文件。所以我需要根据系统属性的存在来设置配置文件。例如,

String currentEnvironment = systemProperties.getProperty("current.environment");
if (currentEnvironment == null) {
  ((ConfigurableEnvironment)context.getEnvironment()).setActiveProfiles("production");
} else {
  ((ConfigurableEnvironment)context.getEnvironment()).setActiveProfiles(currentEnvironment);
}
但是,我不知道我能在哪里做到这一点。根据{{​​3}}相关问题,可以在我的初始化程序类中覆盖createRootApplicationContext方法。但是,该答案还依赖于在设置配置文件之前加载的配置类。

我想做的是什么?如果是这样,怎么样?

2 个答案:

答案 0 :(得分:6)

覆盖createRootApplicationContextcreateServletApplicationContext对我不起作用。我遇到了各种错误,例如非法状态异常和“$ {spring.profiles.active}”无法解析。挖掘AbstractAnnotationConfigDispatcherServletInitializer的继承树我设计了以下解决方案:

public class ApplicationInitializer
  extends AbstractAnnotationConfigDispatcherServletInitializer
{
  @Override
  public void onStartup(ServletContext context) throws ServletException {
    super.onStartup(context);

    String activeProfile = System.getProperty("your.profile.property");
    if (activeProfile == null) {
      activeProfile = "prod"; // or whatever you want the default to be
    }

    context.setInitParameter("spring.profiles.active", activeProfile);
  }
}

现在您可以创建如下所示的配置类,它可以正常工作:

@Configuration
@PropertySource( value = "classpath:application-${spring.profiles.active}.properties" )
public class MyAppBeans {
  @Autowired
  private Environment env;

  @Bean
  public Object coolBean() {
    String initParam = this.env.getProperty("cool.bean.initParam");
    ...
    return coolBean;
  }
}

当然,您可以通过VM选项(-Dyour.profile.property=dev)或容器属性(例如Tomcat容器属性)设置“your.profile.property”。

答案 1 :(得分:0)

而不是

@PropertySource( value = "classpath:application-${spring.profiles.active}.properties" )

你也可以

@PropertySource( value = "classpath:application.properties" )

并使用一些maven插件,例如properties-maven-plugin(*)

   <build>
      <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>properties-maven-plugin</artifactId>
         <version>1.0-alpha-2</version>
         <executions>
            <execution>
               <phase>generate-resources</phase>
               <goals>
                  <goal>write-active-profile-properties</goal>
               </goals>
               <configuration>
                  <outputFile>src/main/resources/application.properties</outputFile>
               </configuration>
            </execution>
         </executions>
      </plugin>
   </build>
   <profiles>
      <profile>
         <id>production</id>
         <properties>
            <profiles>prod</profiles>
            <propertyOne>...</propertyOne>
            <propertyTwo>...</propertyTwo>
         </properties>
      </profile>
      <profile>
         <id>development</id>
         <properties>
            <profiles>dev</profiles>
            <propertyOne>...</propertyOne>
         </properties>
      </profile>
   </profiles>

然后运行

mvn <lifecycle> -P production

有一些理由支持在系统属性中传递活动配置文件而不是maven参数吗?

使用此配置this solution为我工作:

@Configuration
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
    {
    protected WebApplicationContext createRootApplicationContext() {
        WebApplicationContext context = super.createRootApplicationContext();
        ((ConfigurableEnvironment) context.getEnvironment()).setActiveProfiles(profiles());
        return context;
    }
        public String[] profiles() {
            InputStream input = getClass().getClassLoader()
                    .getResourceAsStream("application.properties");
            Properties properties = new Properties();
            try {
                properties.load(input);
            return properties.getProperty("profiles").split(",");;
            } catch (IOException e) {
                e.printStackTrace();
                String[] defaultProfiles = {"dev"};
                return defaultProfiles;
                // I really think that here we shouldn't return a default profile
            }

        }
}

(*)这是一个旧插件(发布日期为2009年),所以也许我们应该找另一个做同样工作的插件,但想法是写属性+ maven配置文件的插件。