如何让 Spring 使用多个上下文自动装配集成测试类?
我的集成测试之一使用多个 Spring 上下文文件。看起来 Spring 只自动装配第一个上下文中的 bean,而不是第二个上下文中的 bean。有谁知道我做错了什么或如何解决该问题?
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-security.xml"}) @Configurable public class UserDetailsServiceImplIntegrationTest { @Autowired UserDataOnDemand dod; // @Autowired does not work for this bean from applicationContext-security.xml UserDetailsService userDetailsService; @Before public void setup() { dod.init(); // workaround for autowiring problem userDetailsService = (UserDetailsService)ctx.getBean("userDetailsService"); } @Test public void testLoadUser() { UserDetails ud = userDetailsService.loadUserByUsername("[email protected]"); Assert.assertEquals("[email protected]", ud.getUsername()); } }
我使用的是Spring 3.0.3。
这是当我取消注释 UserDetailsService 的 @Autowired 行时的堆栈跟踪:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'za.co.acme.app.security.UserDetailsServiceImplIntegrationTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.security.core.userdetails.UserDetailsService za.co.acme.app.security.UserDetailsServiceImplIntegrationTest.userDetailsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.security.core.userdetails.UserDetailsService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374) at org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:140) at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:59) at org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:89) at za.co.acme.app.security.UserDetailsServiceImplIntegrationTest.(UserDetailsServiceImplIntegrationTest.java:25) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:202)
该 bean 肯定存在,因为“按名称”查找有效,并且它的类型正确。
One of my integration tests uses multiple Spring context files. It seems that Spring only autowires in beans from the first context and not the second. Does anyone know what I am doing wrong or how to work around the problem?
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-security.xml"}) @Configurable public class UserDetailsServiceImplIntegrationTest { @Autowired UserDataOnDemand dod; // @Autowired does not work for this bean from applicationContext-security.xml UserDetailsService userDetailsService; @Before public void setup() { dod.init(); // workaround for autowiring problem userDetailsService = (UserDetailsService)ctx.getBean("userDetailsService"); } @Test public void testLoadUser() { UserDetails ud = userDetailsService.loadUserByUsername("[email protected]"); Assert.assertEquals("[email protected]", ud.getUsername()); } }
I am using Spring 3.0.3.
Here is the stack trace when I uncomment the @Autowired line for UserDetailsService:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'za.co.acme.app.security.UserDetailsServiceImplIntegrationTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.security.core.userdetails.UserDetailsService za.co.acme.app.security.UserDetailsServiceImplIntegrationTest.userDetailsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.security.core.userdetails.UserDetailsService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374) at org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:140) at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:59) at org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:89) at za.co.acme.app.security.UserDetailsServiceImplIntegrationTest.(UserDetailsServiceImplIntegrationTest.java:25) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:202)
The bean is definitely there since the "by name" lookup works, and it is of the correct type.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
解决方法是创建一个新的单个配置文件(我们称之为“test-configuration.xml”),其中包含 applicationContext.xml 和 applicationContext-security.xml。然后您可以在测试中使用这些配置。
test-configuration.xml:
UserDetailsServiceImplIntegrationTest.java:
A workaround is to create a new single configuration file (let's call it "test-configuration.xml") which is including the both applicationContext.xml and applicationContext-security.xml. Then you can use these configurations within your tests.
test-configuration.xml:
UserDetailsServiceImplIntegrationTest.java:
我有一个类似的设置,它对我来说工作得很好。
我的猜测是问题出在您的项目设置中。你使用 Eclipse 吗?它是从 /bin 文件夹还是 /src 文件夹加载上下文文件?您是否从构建中排除了“applicationContext-security.xml”?
I have a similar setup and it's working fine for me.
My guess is that the problem is in the setup of your project. Do you use Eclipse? Does it load the context files from the /bin folder or from a /src folder? Did you exclude "applicationContext-security.xml" from the build?
我遇到了同样的问题,解决我的问题的解决方案是通过接口切换 bean 暴露。 (即)您的引用 Bean 类型应该是一个接口,而不是其实现类
在您的情况下,更改具体类
UserDetailsService
及其接口的引用。例如:
注意:我知道这不是一个明智的解决方案,但尝试一下,我因为同样的错误而担心很多,最后更改了我的参考并且它起作用了美好的。希望它能解决您的问题。
I had the same problem, the solution fixed my problem is switch the bean expose through Interface. (i.e) Your reference Bean Type should be a Interface instead of its implementation class
In your case change the concrete Class
UserDetailsService
reference with its interface.For Example:
NOTE: I know this wont be a sensible solution, But just give a try, I worried lot because of this same error and finally changed my reference and it worked fine. Hope it would resolve your issue.
您需要告诉 Spring 对这些注释进行操作。在相关的上下文文件中,您应该添加以下内容:
现在它将扫描这些注释。请参阅 Spring 文档 基于注释的配置
要限制需要扫描的类数量,这样您就不必不必要地扫描没有自动装配的包,请添加以下内容:
请参阅 自动检测组件 了解更多信息,以及您需要添加到的 XML 命名空间引用这些标签。
You need to tell Spring to act on those annotations. In the relevant context file you should add the following:
Now it'll scan for those annotations. See the Spring documentation on Annotation-based configuration
To limit the number of classes it needs to scan so you don't needlessly scan packages with no autowiring, add this:
See the docs for Auto-detecting components for more on that, as well as the XML namespaces you'll need to add to reference those tags.
xml 中
userDetailsService
的 bean 名称是什么?您可能需要添加带有 bean 名称的@Qualifier
注释,然后在上下文中放置
标记。看看 Spring 关于该主题的文档。
What is the name of the bean for
userDetailsService
in your xml? You might need to add a@Qualifier
annotation with the bean name, and then putting a<qualifier>
tag in the context.Take a look at Spring's documentation on the topic.
我有同样的问题。似乎有一个代理 UserDataOnDemand 而不是真正的 UserDataOnDemand 。
I have the same problems.It seems that there is a proxy UserDataOnDemand instead of the real UserDataOnDemand .