区别与“位置”或“类”和@ImportResource

区别与“位置”或“类”和@ImportResource

问题描述:

我有一个包含一个单元测试,建立这样一个Java的Spring MVC应用程序相同的配置:区别与“位置”或“类”和@ImportResource

// A configuration class. 
@Configuration 
@ImportResource({ 
    "classpath:configuration/applicationContext.xml", 
    "classpath:configuration/applicationContext2.xml", 
    "classpath:configuration/applicationContext3.xml" 
}) 
public class UnitTestConfiguration { 
} 

// The unit test. 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = {UnitTestConfiguration.class}) 
@WebAppConfiguration() 
public class AuditRecordControllerTest { 
    // Tests 
} 

单元测试工作正常这条路。不过,如果我更改了单元测试的注解以下(同时保持代码完全相同的其余部分):

// The unit test. 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { 
    "classpath:configuration/applicationContext.xml", 
    "classpath:configuration/applicationContext2.xml", 
    "classpath:configuration/applicationContext3.xml" 
}) 
@WebAppConfiguration() 
public class MyUnitTest { 
    // Tests. 
} 

...然后测试失败,甚至正常运行,给我贴在下面的错误。什么改变了?我(显然错误地)认为这两个设置只是两个选择应该有相同的结果,但显然有些事情是不同的,导致后者失败。

有人可以解释使用@ContextConfiguration与“位置”并将其与“类”一起使用以引用配置类加载完全相同的位置之间的区别?

异常发生:

java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99) 
    at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101) 
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:161) 
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:101) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:324) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:213) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:290) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:292) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 
Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Duplicate <global-method-security> detected. 
Offending resource: class path resource [configuration/applicationContext.xml] 
    at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70) 
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85) 
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:72) 
    at org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParser.registerAdvisor(GlobalMethodSecurityBeanDefinitionParser.java:382) 
    at org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParser.parse(GlobalMethodSecurityBeanDefinitionParser.java:259) 
    at org.springframework.security.config.SecurityNamespaceHandler.parse(SecurityNamespaceHandler.java:106) 
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1424) 
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1414) 
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:187) 
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:141) 
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:110) 
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508) 
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:391) 
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:335) 
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303) 
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180) 
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216) 
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187) 
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromImportedResources(ConfigurationClassBeanDefinitionReader.java:313) 
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:138) 
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:116) 
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:324) 
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243) 
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254) 
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94) 
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:609) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) 
    at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:132) 
    at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:59) 
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100) 
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250) 
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64) 
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91) 
    ... 28 more 

原来,@Configuration实际上是另一种类型的专门@Component。这意味着如果在组件扫描期间发现它,它将包含的xml配置将被加载。这正是在第二准备使我的错误:

  • applicationContext.xml包含行<context:component-scan base-package="com.epathlogic.pole" />
  • 发现组件扫描UnitTestConfiguration,因为它使用@Configuration进行注释,因此它定义的xml配置会自动应用。
  • 由于UnitTestConfiguration定义的配置与已经为单元测试加载的配置相同,因此它现在开始加载导致错误的重复项。

当我从UnitTestConfiguration中删除@Configuration时,一切都按预期工作。所以直到我删除之后,这两个设置确实是具有相同结果的替代方案。