使用java配置在Spring中处理多个概要文件的最佳实践是什么?
在我目前正在进行的一个项目中,我们需要多个配置文件,即“默认”和“测试”。为了解决这个问题,我们实现了一个主上下文类ApplicationContext.java,其中包含两个公共静态内部类:一个定义默认概要文件,另一个定义测试概要文件。我们的web.xml设置为目标ApplicationContext.java 代码如下:使用java配置在Spring中处理多个概要文件的最佳实践是什么?,java,spring,Java,Spring,在我目前正在进行的一个项目中,我们需要多个配置文件,即“默认”和“测试”。为了解决这个问题,我们实现了一个主上下文类ApplicationContext.java,其中包含两个公共静态内部类:一个定义默认概要文件,另一个定义测试概要文件。我们的web.xml设置为目标ApplicationContext.java 代码如下: @Configuration //import common beans public class ApplicationContext { @Configurati
@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
}
}
我的问题是,主上下文类ApplicationContext.java位于生产环境(即src/main/java)中,引用了测试环境中的文件。如果有一种更好的方法来定义这些概要文件,而不将这种依赖关系从生产代码引入测试代码,那当然会更好
我们已经在一个测试类中使用jetty实例测试了这些案例,该测试类是从一个main方法开始的。此实例使用以下命令运行:
System.setProperty("spring.profiles.active", "test");
使用Maven的特性分离主应用程序上下文和测试应用程序上下文 例如,如果主应用程序上下文位于 src/main/webapp/WEB-INF/myapp-config.xml 您可以将测试应用程序上下文放入 src/test/webapp/WEB-INF/myapp-config.xml
如果配置文件之间的所有bean都是公共的(即
DefaultContext
和TestContext
都包含相同的bean定义),请为依赖项定义一个接口,例如:
public interface SystemConfiguration {
public DataSource getDataSource();
public SomeService getService();
}
然后使用此接口实现每个概要文件:
@Profile("production")
@Configuration
public class ProductionConfiguration implements SystemConfiguration {
public DataSource getDataSource() {
// create and return production datasource
}
public SomeService getService() {
// Create and return production service
}
}
然后做同样的测试
@Profile("test")
@Configuration
public class TestConfiguration implements SystemConfiguration {
public DataSource getDataSource() {
// create and return dummy datasource
}
public SomeService getService() {
// Create and return dummy service
}
}
然后,您可以将其注入到主配置中:
@Configuration
public class ApplicationContext {
@Autowired
private SystemConfiguration systemConfiguration;
}
我们最终得到的解决方案利用了Spring的@ComponentScan注释。各种应用程序上下文在多个maven模块中定义。但是,通过共享相同的包命名(即com.company.application.context),此注释可以在测试和生产目录中查找上下文 生成的代码:
@ComponentScan("com.company.application.context")
@Configuration
public class ApplicationContext { }
假设maven依赖项和包命名正确,所有生产上下文和测试上下文都会自动找到。生产上下文如下所示:
@Configuration
@Profile("default")
//Import contexts from other modules
public class ProductionContext { }
对于测试上下文也是如此。使用以下行从主方法运行Jetty将正确加载测试上下文并忽略“默认”bean:
该解决方案避免了从生产到测试代码的任何直接引用,尽管maven依赖关系是必要的 问题是,我们希望从java主方法启动Jetty,而不是从带有maven commandPlus的cmd启动Jetty,主要区别在于maven概要文件为每个概要文件生成不同的构建。因此,本地开发的构建不同于发布环境。在我看来,这是一种错误的方法,构建应该是相同的,以保证兼容性。考虑到我们应用程序的复杂性,这是不实际的。你提出的解决方案确实非常优雅。我们在这个解决方案中遇到的一个问题是,其中一个关键bean是在子模块中定义的,与主模块没有依赖关系(其中定义了ApplicationContext)。
System.setProperty("spring.active.profiles", "test");