0

我有一个 spring-mvc 网络应用程序。

以下代码已被简化和清理以保护有罪者。基本思想是我有两个独立的上下文配置文件:一个用于 MVC,另一个用于一般配置文件。

当 Spring 连接控制器时,我得到:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'configController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.ConfigBean com.example.ConfigController.config; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.example.ConfigBean] 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)}

但是,来自另一个 servlet 的以下代码可以正常工作:

WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());            
ConfigBean config = context.getBean(ConfigBean.class);        

这向我表明,MVC 组件扫描器由于某种原因看不到配置内容。我试过添加

<import resource="config.xml" />

dispatcher-servlet.xml,但这并没有什么不同。无论如何感觉不对,因为我不想要配置 bean 的两个实例。即使手动将 ConfigBean 声明复制到 dispatcher.xml 中也不能解决我的问题,这表明我正在做一些非常愚蠢的事情。关于我可能遗漏的任何建议?

我的详细配置如下:

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/dispatcher-servlet.xml
            /WEB-INF/config.xml
        </param-value>
    </context-param>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

... Some other non-spring stuff ...

</web-app>

调度程序-servlet.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:annotation-config />
    <context:component-scan base-package="com.example" />

    <mvc:annotation-driven />

</beans>

类路径:config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util.xsd">

    <bean class="com.example.ConfigBean">
        <property name="foo" value="bar" />
    </bean>
</beans>

配置控制器.java

package com.example;

import com.example.ConfigBean

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/config")
public class ConfigController {

    @Autowired 
    private ConfigBean config;

    @RequestMapping(method=RequestMethod.GET) 
    public @ResponseBody ConfigBean getConfig() {
        return config;
    }
}
4

3 回答 3

2

可能是因为你添加/WEB-INF/dispatcher-servlet.xmlcontextConfigLocationin context-param

它不是必需的,因为 web 应用程序上下文将根据 displater servlet 名称准备文件

来自Spring 文档

在初始化 DispatcherServlet 时,Spring MVC 在您的 Web 应用程序的 WEB-INF 目录中查找名为 [servlet-name]-servlet.xml 的文件并创建在那里定义的 bean,覆盖任何同名定义的 bean 的定义在全球范围内。

于 2013-06-17T03:48:49.540 回答
1

我认为由于存在多个 ConfigBean bean 实例,自动装配失败。错误消息有点令人困惑。如果 bean 丢失或有多个实例,您会收到相同的错误。

问题在于 dispatcher-servlet.xml 中的组件扫描。假设 ConfigBean 类也被注释了,@Component或者它的子类型之一将被创建两个实例。一次用于 config.xml 中的 bean 定义,一次用于组件扫描。

要解决此问题,您需要更改组件扫描以忽略非控制器类。

<context:component-scan  user-default-filters='false'>
  <context:include-filter annotation="org.springframework.stereotype.Controller"/>
</context:component-scan>

另一个 servlet 类中的查找正在工作,因为您正在直接访问根应用程序上下文。

于 2013-06-17T03:45:55.087 回答
0

这确实很愚蠢。该<context:annotation-config />指令应该在 config.xml 中,而不是 dispatcher-servlet.xml 中。

据我了解,注释的东西在父上下文中,所以这就是指令所属的地方。

于 2013-07-09T02:22:38.123 回答