使用 java config 在 Spring 中处理多个配置文件的最佳实践是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15903514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best practice for handling multiple profiles in Spring with java config?
提问by Jarle Svendsrud
On a project I'm currently working on we have the need for multiple profiles, i.e. "default" and "test". To solve this, we've implemented a main context class, ApplicationContext.java, with 2 public static inner classes: one of them defines the default profile, the other defines the test profile. Our web.xml is set to target ApplicationContext.java.
在我目前正在进行的一个项目中,我们需要多个配置文件,即“默认”和“测试”。为了解决这个问题,我们实现了一个主上下文类 ApplicationContext.java,它有 2 个公共静态内部类:其中一个定义默认配置文件,另一个定义测试配置文件。我们的 web.xml 设置为目标 ApplicationContext.java。
Code as follows:
代码如下:
@Configuration
//import common beans
public class ApplicationContext {
@Configuration
@Profile("default")
public static class DefaultContext {
//default beans
}
@Configuration
@Profile("test")
public static class TestContext {
//test beans
}
}
My problem with this is that the main context class, ApplicationContext.java, is in the production environment (i.e. src/main/java) with references to files in the test environment. If there is a better way to define these profiles without introducing this dependency from production code to test code, that would of course be preferable.
我的问题是主上下文类 ApplicationContext.java 位于生产环境(即 src/main/java)中,并引用了测试环境中的文件。如果有更好的方法来定义这些配置文件,而不会在生产代码到测试代码之间引入这种依赖性,那当然更好。
We`ve tested these cases with a jetty instance in a test class, started from a main method. This instance is run with the following command:
我们已经用测试类中的一个码头实例测试了这些案例,从一个 main 方法开始。此实例使用以下命令运行:
System.setProperty("spring.profiles.active", "test");
采纳答案by Jarle Svendsrud
The solution we ended up with utilizes Spring`s @ComponentScan annotation. The various application contexts are defined in multiple maven modules. However, by sharing the same package naming (i.e. com.company.application.context) this annotation finds the contexts across both test and production directories.
我们最终得到的解决方案利用了 Spring 的 @ComponentScan 注释。各种应用程序上下文在多个 maven 模块中定义。但是,通过共享相同的包命名(即 com.company.application.context),该注释可以跨测试和生产目录查找上下文。
The resulting code:
结果代码:
@ComponentScan("com.company.application.context")
@Configuration
public class ApplicationContext { }
All production contexts and test contexts are found automatically, assuming maven dependencies and package naming is correct. The production context looks like this:
假设 Maven 依赖项和包命名正确,所有生产上下文和测试上下文都会自动找到。生产环境如下所示:
@Configuration
@Profile("default")
//Import contexts from other modules
public class ProductionContext { }
Likewise for test context. Running Jetty from a main method with the following line correctly loads the test context and ignores the "default" beans:
同样对于测试上下文。使用以下行从主方法运行 Jetty 正确加载测试上下文并忽略“默认”bean:
System.setProperty("spring.active.profiles", "test");
This solution avoids any direct references from production to test code, although maven dependencies are necessary.
该解决方案避免了从生产到测试代码的任何直接引用,尽管 maven 依赖是必要的。
回答by NilsH
If all the beans are common between your profiles (that is, both DefaultContext
and TestContext
contains the same bean definitions), define an interface for the dependencies, e.g:
如果所有的豆类都是常见的配置文件之间(即,既DefaultContext
和TestContext
包含相同的bean定义),定义了依赖性,如接口:
public interface SystemConfiguration {
public DataSource getDataSource();
public SomeService getService();
}
Then implement each profile with this interface:
然后使用此接口实现每个配置文件:
@Profile("production")
@Configuration
public class ProductionConfiguration implements SystemConfiguration {
public DataSource getDataSource() {
// create and return production datasource
}
public SomeService getService() {
// Create and return production service
}
}
And then do the same for test.
然后做同样的测试。
@Profile("test")
@Configuration
public class TestConfiguration implements SystemConfiguration {
public DataSource getDataSource() {
// create and return dummy datasource
}
public SomeService getService() {
// Create and return dummy service
}
}
Then you can inject this into your main configuration:
然后你可以将它注入到你的主配置中:
@Configuration
public class ApplicationContext {
@Autowired
private SystemConfiguration systemConfiguration;
}
回答by Qwerky
Use the features of Maven to seperate main and test application contexts.
使用 Maven 的特性来分离主应用上下文和测试应用上下文。
For example if your main application context lives in
例如,如果您的主要应用程序上下文位于
src/main/webapp/WEB-INF/myapp-config.xml
src/main/webapp/WEB-INF/myapp-config.xml
you can put a test application context in
您可以将测试应用程序上下文放入
src/test/webapp/WEB-INF/myapp-config.xml
src/test/webapp/WEB-INF/myapp-config.xml