如何从返回接口的方法(@Bean)注入xml中的Bean(com.typesafe.config.Config)?

时间:2017-02-15 18:28:14

标签: spring dependency-injection spring-java-config spring-bean typesafe-config

我有一个基于xml-config的spring应用程序,其中一个bean需要一个com.typesafe.config.Config参数作为构造函数参数。 为此,我们有一个@Configuration类,其中一个方法(注释为@Bean)返回一个com.typesafe.config.Config对象。

但是当春天开始时它会抱怨“无法实例化[com.typesafe.config.Config]:指定的类是一个接口”

如何通过xml将getconfig返回对象注入构造函数?

这是为了摆脱应用程序逻辑而简化的代码片段:

import com.typesafe.config.Config;
...
public class myFilter implements Filter {
  public myFilter(Config aconfig) {
        ...
  }
}

然后我有一个JavaConfig类,它创建了我需要在myFilter构造函数中注入的bean:

@org.springframework.context.annotation.Configuration
public class TSConfiguration {
   ...
   @Bean(name = "app-config")
   public Config getConfig() {
     ...
   }
}

我在spring.xml文件中添加了以下内容:

<beans:bean class="TSConfiguration" />
<beans:bean id="app-config" class="com.typesafe.config.Config"/>
<beans:bean id="theFilter" class="myFilter">
   <beans:constructor-arg index="0" ref="app-config"/>
 </beans:bean>

以下是Spring的例外:

15-Feb-2017 13:19:55.463 SEVERE [localhost-startStop-1] org.springframework.web.context.ContextLoader.initWebApplicationContext Context initialization failed
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'app-config' defined in ServletContext resource [/WEB-INF/spring-security.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.typesafe.config.Config]: Specified class is an interface

感谢名单。

2 个答案:

答案 0 :(得分:1)

违规行是:

<beans:bean id="app-config" class="com.typesafe.config.Config"/>

由于你已将它放在 spring.xml 中,因此Spring试图从app-config实例化一个名为Config的bean。但Config是一个接口,因此Spring无法实例化它,从而导致错误。

我认为,一旦删除它,Spring将选择使用@Bean实例化的getConfig。如果这不起作用,请查看TSConfiguration是否正确导入 spring.xml

答案 1 :(得分:0)

要添加到另一个答案,您要声明两次可能是同一个bean的内容。

在这里,您告诉Spring创建一个名为app-config的Config类型的bean:

 @Bean(name = "app-config")
 public Config getConfig(){

在这里,您尝试创建另一个Config类型的bean,其ID为app-config

 <beans:bean id="app-config" class="com.typesafe.config.Config"/>

如果在JavaConfig中声明一个bean,则无需再次在XML中声明它,反之亦然(假设您的目的是拥有该类型的单个bean)。

而且,正如已经指出的那样,你无法实例化一个接口。

更新:

我基本上会中途忽略你发布的代码,因为似乎对注释的作用以及如何使用它们有误解。

首先,如果你想用纯XML做所有事情,你就不能这样做:

<beans:bean id="app-config" class="com.typesafe.config.Config"/>

您需要对该接口进行具体实现。但是,根据您发布的内容,您有一个您正在使用的配置类。让我们从那开始:

package com.testpackage;

@Configuration
public class Config {


        @Bean
        public SomeInterface someImplementation(){
            return new SomeInterface() {
                @Override
                public String implementation() {
                    return "String";
                }
            };
        }
    }

这表示创建一个SomeInterface类型的bean。此bean的名称将继承方法名称someImplementation,因此手动为其命名没有意义。请注意,虽然这是返回一个接口,但我们正在创建一个匿名类并返回它。

接下来,我们将看一下上面的XML:

<beans>
        <context:component-scan base-package="com.testpackage"/>

        <bean class="com.testpackage.ConcreteClass">
            <constructor-arg index="0" ref="someImplementation"/>
        </bean>
</beans>

请注意,我们正在扫描(context:component-scan)包中的配置。如果我们使用@Configuration注释,我们可以进行组件扫描。

下面的示例执行相同的操作,但只需手动声明配置bean:

<beans>
        <bean class="com.testpackage.Config"/>

        <bean class="com.testpackage.ConcreteClass">
            <constructor-arg index="0" ref="someImplementation"/>
        </bean>
</beans>

如果您手动声明上面的Config类,则不需要使用@Configuration 对其进行注释。该注释的要点是组件扫描到&#34;参见&#34; bean并实例化它。由于我们手动执行此操作,因此不需要注释。

而且,为了完整起见,这是一个单元测试,验证一切正常:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:META-INF/appContextTest.xml"})
public class SomeTester {


    @Autowired
    ConcreteClass concreteClass;

    @Test
    public void test(){
        assertEquals("String", concreteClass.impl.implementation());
    }
}