Deb*_*kia 2 java spring spring-mvc
我有一个Spring控制器定义如下:
@Controller
@RequestMapping("/queue")
public class QueueController {
QueuesService queueService;
public QueueController(QueuesService queueService) {
if (queueService == null) {
throw new IllegalArgumentException("QueueService cannot be null");
}
this.queueService = queueService;
}
}
Run Code Online (Sandbox Code Playgroud)
我的context-configuration文件中的相应条目如下(其中bean定义没有任何"id"属性):
<bean class="com.xy.web.controllers.QueueController">
<constructor-arg ref="queueServiceImpl"></constructor-arg>
</bean>
Run Code Online (Sandbox Code Playgroud)
现在,在应用程序启动期间,Spring正在抛出异常:
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.xy.web.controllers.QueueController]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.xy.web.controllers.QueueController.<init>()
Run Code Online (Sandbox Code Playgroud)
但是,当我将"id"属性添加到"bean定义"(如下所示)时,它的创建正确.
<bean id="queueController" class="com.xy.web.controllers.QueueController">
<constructor-arg ref="queueServiceImpl"></constructor-arg>
</bean>
Run Code Online (Sandbox Code Playgroud)
对此的任何解释或我在这里遗漏了什么?
我假设你<content:component-scan ...>
的配置在某个地方.这将尝试实例化任何带@Component
注释的类.@Controller
是的,@Component
所以Spring会尝试QueueController
使用类默认的空构造函数进行实例化.在您的情况下,这样的构造函数不存在.因此它会抛出您所看到的异常.
您需要添加一个空构造函数
public QueueController() {}
Run Code Online (Sandbox Code Playgroud)
无论您的bean声明如何都会发生这种情
<bean class="com.xy.web.controllers.QueueController">
<constructor-arg ref="queueServiceImpl"></constructor-arg>
</bean>
Run Code Online (Sandbox Code Playgroud)
你将最终得到两个QueueController
实例.这可能不是你想要的.
至于你因为id而看到的行为:
当应用程序上下文读取时,component-scan
它将BeanComponentDefinition
使用名称注册一个queueController
.然后上下文继续进行bean声明.因为您已指定id
等于先前的定义,所以它将覆盖它.您最终只能为您的QueueController
班级定义一个bean定义.由于bean声明需要一个具有特定参数的构造函数,并且你拥有它,它不会抱怨并将创建bean.
如果您指定了另一个id
,那么abcd
您的应用程序上下文将注册两个BeanDefinitions:一个名称queueController
(遵循默认名称生成策略)component-scan
和一个名称abcd
来自<bean>
声明.将queueController
需要一个你没有默认的构造函数.因此,您将获得例外.
更详细
如果您正在使用a ClassPathXmlApplicationContext
,请查看该ClassPathBeanDefinitionScanner#doScan(String...)
方法的以下调用
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
Run Code Online (Sandbox Code Playgroud)
这beanNameGenerator
是一个实例AnnotationBeanNameGenerator
.它最终打电话
// Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
Run Code Online (Sandbox Code Playgroud)
哪个叫
String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
return Introspector.decapitalize(shortClassName);
Run Code Online (Sandbox Code Playgroud)
返回默认名称queueController
.这就是你要id
覆盖的那个.
你可以在日志中看到这个:
Mon Aug 26 12:12:15 EDT 2013 [main] INFO o.s.b.f.s.DefaultListableBeanFactory - Overriding bean definition for bean 'queueController': replacing [Generic bean: class [org.test.QueueController]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Users\sotirios.delimanolis\git\content-store\target\test-classes\org\test\QueueController.class]] with [Generic bean: class [org.test.QueueController]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [app.xml]]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1090 次 |
最近记录: |