其他分享
首页 > 其他分享> > Spring无法按配置文件选择自动装配实现

Spring无法按配置文件选择自动装配实现

作者:互联网

我试图找出如何使用@Autowired批注在Spring中进行模拟实现.我试图通过配置文件以这种方式来驱动:

>有一个默认配置文件,当未定义配置时运行
>指定测试配置文件后,它将自动装配模拟对象,而不是默认实现.

在追求这种设置时,我遇到了一个问题,即Spring似乎无法分辨出我的实现之间的区别.我正在使用Tomcat / Jersey / Maven / Spring,并且没有使用任何xml配置.这是相关代码的摘要(viewable on my example GitHub).

问题:通过mvn clean tomcat7:run运行并导航到’/ foo / bar’会产生以下异常(下面的完整堆栈跟踪):没有定义类型为[dkwestbr.spring.autowired.example.IStringGetter]的合​​格Bean:预期的单个匹配bean,但发现2:a,b

我意识到问题是Spring无法区分我的两种实现,但是我很难找到如何正确地声明我想要默认情况下的a和仅当运行mvn test时才b的问题.

我的初始值设定项:

    @Override
    public void onStartup(ServletContext context) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(AppConfig.class);

        context.addListener(new ContextLoaderListener(appContext));

        /*
        for(String profile: appContext.getEnvironment().getActiveProfiles()) {
            System.out.println(String.format("Active profile: %s", profile));
        }
        */

        Map<String, String> filterParameters = new HashMap<>();

        // set filter parameters
        filterParameters.put("com.sun.jersey.config.property.packages", "dkwestbr.spring.autowired.example");
        filterParameters.put("com.sun.jersey.config.property.JSPTemplatesBasePath", "/WEB-INF/app");
        filterParameters.put("com.sun.jersey.config.property.WebPageContentRegex", "/(images|css|jsp)/.*");


        SpringServlet servlet = new SpringServlet();   
        ServletRegistration.Dynamic servletDispatcher = context.addServlet("jersey-servlet", servlet);
        servletDispatcher.setInitParameters(filterParameters);
        servletDispatcher.setLoadOnStartup(1);
        servletDispatcher.addMapping("/*");
    }

我的配置:

@Configuration
@ComponentScan(basePackages = {"dkwestbr.spring.autowired.example"})
public class AppConfig {

    @Bean
    private static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Configuration
    @PropertySource("classpath:configuration.properties")
    static class Production { }

    @Configuration
    @Profile("test")
    @PropertySource("classpath:configuration.properties")
    static class Test { }
}

我的Web端点有问题的@Autowired变量:

@Path("/foo")
@Component
public class WebEndpoint {

    @Autowired
    private IStringGetter getTheThing;

    @GET
    @Path("/bar")
    @Produces(MediaType.TEXT_HTML)
    public String getStuff() {
        System.out.println(getTheThing.getItGood());
        return String.format("<html><body>Hello - %s</body></html>", getTheThing.getItGood());
    }
}

我的第一个实现(我希望这是默认设置):

@Component
public class A implements IStringGetter {

    @Value("${my.property}")
    private String configValue;

    @Override
    public String getItGood() {
        return String.format("I am an A: %s", configValue);
    }

}

我的第二个实现(仅在运行mvn test时才需要):

@Component
@ActiveProfiles("test")
public class B implements IStringGetter {

    @Value("${my.property}")
    private String configValue;

    @Override
    public String getItGood() {
        return String.format("I am an B: %s", configValue);
    }
}

完整堆栈跟踪:

10:22:49.136 [localhost-startStop-1] ERROR org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webEndpoint': Injection of autowired dependencies failed; nes
ted exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dkwestbr.spring.autowired.example.IString
Getter dkwestbr.spring.autowired.example.WebEndpoint.getTheThing; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionExcepti
on: No qualifying bean of type [dkwestbr.spring.autowired.example.IStringGetter] is defined: expected single matching bean but found 2: a,b
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostPro
cessor.java:288) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116) ~[
spring-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) ~[s
pring-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spr
ing-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) ~[spring-beans-3.2.4.RELEASE.jar:3
.2.4.RELEASE]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-
3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) ~[spring-beans-3.2.4.RELEASE.jar:3.2
.4.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4
.RELEASE]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628) ~[sprin
g-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spri
ng-context-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) ~[spring-context-3.2.4.RELEASE
.jar:3.2.4.RELEASE]
        at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) ~[spring-web-3.2.4.RELEASE.
jar:3.2.4.RELEASE]
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) [spring-web-3.2.4.RELEASE.jar:3.2.4.RELEAS
E]
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [spring-web-3.2.4.RELEASE.jar:3.2
.4.RELEASE]
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797) [tomcat-embed-core-7.0.37.jar:7.0.37]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291) [tomcat-embed-core-7.0.37.jar:7.0.37]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-7.0.37.jar:7.0.37]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [tomcat-embed-core-7.0.37.jar:7.0.37]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [tomcat-embed-core-7.0.37.jar:7.0.37]
        at java.util.concurrent.FutureTask.run(FutureTask.java:262) [?:1.7.0_40]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [?:1.7.0_40]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [?:1.7.0_40]
        at java.lang.Thread.run(Thread.java:724) [?:1.7.0_40]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dkwestbr.spring.autowired.example.IStringGetter
 dkwestbr.spring.autowired.example.WebEndpoint.getTheThing; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
 qualifying bean of type [dkwestbr.spring.autowired.example.IStringGetter] is defined: expected single matching bean but found 2: a,b
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPost
Processor.java:514) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4.RE
LEASE]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostPro
cessor.java:285) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        ... 22 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [dkwestbr.spring.autowired.example.IStringGe
tter] is defined: expected single matching bean but found 2: a,b
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:865) ~[spring-bea
ns-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) ~[spring-beans
-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPost
Processor.java:486) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4.RE
LEASE]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostPro
cessor.java:285) ~[spring-beans-3.2.4.RELEASE.jar:3.2.4.RELEASE]
        ... 22 more
Oct 11, 2013 10:22:49 AM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webEndpoint': Injection of autowired dependencies failed; nes
ted exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dkwestbr.spring.autowired.example.IString
Getter dkwestbr.spring.autowired.example.WebEndpoint.getTheThing; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionExcepti
on: No qualifying bean of type [dkwestbr.spring.autowired.example.IStringGetter] is defined: expected single matching bean but found 2: a,b
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostPro
cessor.java:288)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
        at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dkwestbr.spring.autowired.example.IStringGetter
 dkwestbr.spring.autowired.example.WebEndpoint.getTheThing; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
 qualifying bean of type [dkwestbr.spring.autowired.example.IStringGetter] is defined: expected single matching bean but found 2: a,b
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPost
Processor.java:514)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostPro
cessor.java:285)
        ... 22 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [dkwestbr.spring.autowired.example.IStringGe
tter] is defined: expected single matching bean but found 2: a,b
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:865)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPost
Processor.java:486)
        ... 24 more

解决方法:

@ActiveProfiles批注是meant to be used for tests.

@ActiveProfiles

A class-level annotation that is used to declare which bean definition
profiles should be active when loading an ApplicationContext for test
classes.

至于如何设置用于组件扫描的配置文件,take a look here.基本上只需将@ActiveProfiles与@Profile切换.

标签:maven,autowired,spring,java,inversion-of-control
来源: https://codeday.me/bug/20191122/2061419.html