Spring 为AbstractAnnotationConfigDispatcherServletInitializer设置可与@PropertySource一起使用的活动配置文件?
我正在使用Spring 为AbstractAnnotationConfigDispatcherServletInitializer设置可与@PropertySource一起使用的活动配置文件?,spring,spring-mvc,spring-3,Spring,Spring Mvc,Spring 3,我正在使用AbstractAnnotationConfigDispatcherServletInitializer配置我的web应用程序。我还有一个@Configuration类,用于创建一些bean。在这个类中,我使用@PropertySource注释为各种设置(例如数据库连接详细信息)加载属性文件 目前,我在Ant任务中使用Maven概要文件为我的运行时环境创建正确的属性文件。也就是说,我让Maven在构建时将“prod.properties”或“dev.properties”移动到“app
AbstractAnnotationConfigDispatcherServletInitializer
配置我的web应用程序。我还有一个@Configuration
类,用于创建一些bean。在这个类中,我使用@PropertySource
注释为各种设置(例如数据库连接详细信息)加载属性文件
目前,我在Ant任务中使用Maven概要文件为我的运行时环境创建正确的属性文件。也就是说,我让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);
}
不过,我不确定我在哪里可以做到这一点。根据一个相关的问题,这可以通过重写我的initializer类中的createRootApplicationContext
方法来完成。但是,这个答案还依赖于在设置概要文件之前加载的配置类
我想做的事可能吗?如果是这样,怎么做?重写
createRootApplicationContext
或createServletApplicationContext
对我不起作用。我遇到了各种错误,如非法状态异常和“${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”
@PropertySource( value = "classpath:application-${spring.profiles.active}.properties" )
你也可以
@PropertySource( value = "classpath:application.properties" )
并使用一些maven插件,比如属性maven plugin(*)
(*)这是一个旧插件(发布日期为2009年),所以也许我们应该找到另一个做同样工作的插件,但想法是针对write properties+maven profiles的插件。@Charles,你为什么要删除[spring-3.2]标签?这很重要。当现有版本标记已覆盖相同区域时,3.2.New版本标记之前不存在主初始值设定项类。
[spring-3]
标签wiki摘录说它适用于所有3.x版本的spring。包括3.2。新特性不会破坏足够的内容,从而严格要求在此处添加新标签。(还要记住主版本标签的问题计数——小于600。碎片是不好的。)重新阅读链接。“在我看来,唯一应该使用c#-4.0标记的问题是那些专门询问4.0中添加的功能细节的问题。”——我问的是3.2的一个特定功能。在createRootApplicationContext
中,注册了配置类,但上下文尚未刷新。@SotiriosDelimanolis感谢您澄清这一点,但我无法让它在覆盖该方法时起作用。+1我认为它不起作用的原因是,尽管上下文未刷新,但您的@Configuration
类”元数据已加载(我也对此进行了更多研究)。如果类注册后未声明,@PropertySource
的占位符,则无法解析该占位符。在解决此解决方案之前,我在覆盖中重新实现了默认方法,添加了配置文件检测,设置了活动配置文件,注册了配置类,并刷新了上下文。春天一点也没有。
<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
@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
}
}
}