【问题标题】:Spring Injection with Servlets: NoSuchBean使用 Servlet 进行 Spring 注入:NoSuchBean
【发布时间】:2013-12-08 19:04:09
【问题描述】:

Spring 新手,正在使用 Spring 3.2.5 尝试让注入与普通 Web 应用程序中的 servlet 一起工作(即,它不是 Spring MVC Web 应用程序 - 它是我正在扩展使用的预先存在的应用程序Spring 框架)。容器是Tomcat 7.0.47。

我的问题是当我点击 servlet 时出现 NoSuchBeanDefinitionException 错误(没有定义名为“MyServlet”的 bean)。启动时没有错误,因此至少我的一个 bean(ServiceImplementation bean)正在成功实例化。当新的 HTTP 请求进来时,问题似乎在于找到 HttpRequestHandler 派生的 bean (MyServlet)。

异常的完整堆栈跟踪是:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'MyServlet' is defined
    org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
    org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1114)
    org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:279)
    org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
    org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121)
    org.springframework.web.context.support.HttpRequestHandlerServlet.init(HttpRequestHandlerServlet.java:58)
    com.random.webapp.MySpringServlet.init(Unknown Source)
    javax.servlet.GenericServlet.init(GenericServlet.java:160)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    java.lang.Thread.run(Thread.java:662)

我按照以下模式进行设置: http://andykayley.blogspot.com/2008/06/how-to-inject-spring-beans-into.html

...有一个小的(我认为)扭曲。我有一个从 HttpRequestHandlerServlet 派生的类,这样我就可以用一些特定于应用程序的东西覆盖 init 方法。扩展类如下所示:

public class MySpringServlet extends HttpRequestHandlerServlet
{
    public void init() throws ServletException
    {
        super.init();
        appSpecificInit();
    }
}

我要注入的 servlet 如下所示:

public class MyServlet implements HttpRequestHandler
{
    private IService _service = null;

    public void setService( IService theService ) {
        _service = theService;
    }

    @Override
    public void handleRequest(HttpServletRequest request,
                              HttpServletResponse response)
                              throws ServletException, IOException
    {
        _service.DoSomething();
    }
}

我希望它注入的实现如下所示:

public class ServiceImplementation implements IService
{
    @Override
    public void DoSomething()
    {
                // some code goes here
    }
}

这些是 web.xml 中的相关条目:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
   "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml /WEB-INF/implementation.xml</param-value>
    </context-param>

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

    <servlet>
            <servlet-name>MyServlet</servlet-name>
            <servlet-class>com.random.webapp.MySpringServlet</servlet-class>
    </servlet>


  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/myservlet/*</url-pattern>
  </servlet-mapping>

</web-app>

这是 applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <bean id="MyServlet" class="com.random.webapp.MyServlet">
    <property name="Service" ref="ServiceImplementation" />
  </bean>

</beans>

...这就是 implementation.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

 <bean id="ServiceImplementation" class="com.random.webapp.ServiceImplementation">
 </bean>

</beans>

我一直在 web.xml、applicationContext.xml 和 implementation.xml 文件之间来回反复检查我的配置,我没有发现其中任何一个有任何问题,但我显然遗漏了什么。

有人有什么想法吗?

【问题讨论】:

  • 添加了完整的异常堆栈跟踪 - 我正在尝试将 ServiceImplementation setter-injected 到 MyServlet 的服务属性中。
  • 我只是复制粘贴了你的整个代码,它对我来说很好用。您确定要向我们展示您的真实配置吗?
  • 确保你清理并重新编译你的项目。
  • 嗯 - 我将应用程序部署到 Tomcat 的方式可能存在问题。我没有从它构建的地方运行它——我正在生成一个 WAR 文件夹并将其内容复制到 Tomcat 的 webapp 文件夹中。我将仔细检查这个部署配置,看看我是否在上面粘了一些东西......

标签: spring servlets dependency-injection


【解决方案1】:

你得到的异常

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'MyServlet' is defined

发生在HttpRequestHandlerServletinit() 方法中,该方法尝试根据您在web.xml 中为HttpRequestHandlerServlet 提供的名称从您的上下文中加载委托HttpRequestHandler 对象

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.random.webapp.MySpringServlet</servlet-class>
</servlet>

在上面的配置中,这将是MyServlet。虽然看起来你在

中是正确的
<bean id="MyServlet" class="com.random.webapp.MyServlet">
    <property name="Service" ref="ServiceImplementation" />
</bean>

确保您正在加载此处声明的正确上下文文件

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml /WEB-INF/implementation.xml</param-value>
</context-param>

【讨论】:

  • 如何验证是否正在加载正确的上下文文件? WEB-INF中只有3个xml文件:web.xml、applicationContext.xml、implementation.xml
  • 我听说 Spring 应用程序上下文可以有层次结构,例如 ROOT 上下文,以及 Web 应用程序中的其他一些上下文。这个概念在这里有用吗?
  • @Hoobajoob 如果他们在那里,你应该没问题。仔细检查内容是否如您所说。至于层次结构,没有。当您声明 ContextLoaderListener 时,您会加载一个上下文,即根上下文。
  • 啊废话 - 这是一个简单的案例错误:myServlet 而不是 MyServlet - 我已经更新了我的工作区中的配置,但没有将更新复制到已部署的 Web 应用程序。谢谢!
  • 从技术上讲,我猜正确答案来自您的 cmets 建议验证配置内容,但我还是将您的答案标记为答案。再次感谢!
猜你喜欢
  • 2012-02-11
  • 2013-09-15
  • 2011-07-06
  • 1970-01-01
  • 2011-02-06
  • 2015-03-01
  • 1970-01-01
  • 2017-05-17
相关资源
最近更新 更多