我有一个基于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
感谢名单。
答案 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());
}
}