使用Spring注入的InstantiationException [英] InstantiationException using Spring injection

查看:80
本文介绍了使用Spring注入的InstantiationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次尝试使用Spring注入。我肯定会忘记一些明显的东西,但我不知道它是什么。

I am experimenting with Spring injection for the first time. I am surely forgetting something obvious but I don't know what it is.

在src / main / java下,我有一个包含 Hello,Animal,猫。

Under src/main/java, I have a package 'example' containing Hello, Animal, Cat.

在src / main / webapp / WEB-INF下,我有web.xml和springapp-servlet.xml。

Under src/main/webapp/WEB-INF, I have web.xml and springapp-servlet.xml.

当我使用Tomcat部署应用程序时,我得到一个:

When I deploy my app with Tomcat, I get a:

javax.servlet.ServletException: Error instantiating servlet class example.Hello
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)

需要进行注射才能缺少什么?

What am I missing for the injection to work?

以下来源:

您好。 java

package example;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class Hello extends HttpServlet {
  private final Animal animal;

  @Autowired
  public Hello(final  Animal animal) {
    this.animal = animal;
  }

  @Override
  protected void doGet(final HttpServletRequest req,
          final HttpServletResponse resp) throws ServletException, IOException {
    resp.getWriter().write(animal.sound());
  }
}

Cat.java

package example;

import org.springframework.stereotype.Service;

@Service
public class Cat implements Animal {
  public String sound() {
    return "Miaou";
  }
}

Animal.java

Animal.java

package example;

public interface Animal {
  public String sound() ;
}

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_2_5.xsd"
    version="2.5">

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

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

    <servlet>
        <servlet-name>Hello</servlet-name>
        <servlet-class>example.Hello</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

springapp-servlet.xml

springapp-servlet.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:mvc="http://www.springframework.org/schema/mvc"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <context:component-scan base-package="example" />
    <mvc:annotation-driven />

</beans>

我最初以为我的springapp-servlet.xml甚至没有被阅读,但是如果我做了我的web.xml中名称springapp-servlet.xml上有错字,在部署时确实出现错误,因此我显然具有springapp-servlet.xml的正确路径。确实有,但注射无效。

I initially thought that perhaps my springapp-servlet.xml was not even read, but if I make a typo on the name springapp-servlet.xml in my web.xml, I do get an error at deployment time, so I clearly have the correct path for springapp-servlet.xml. It is being but yet the injection isn't working.

更新:

由于下面的答案,我在下面显示了对我有用的解决方案。除Hello外,所有代码均保持不变:

I am showing below the solution that worked for me thanks to the answers below. All code remains the same except for Hello:

Hello.java

Hello.java

public class Hello extends HttpServlet {

  @Inject
  private Animal animal;

  @Override
  public void init(final ServletConfig config) throws ServletException {
    super.init(config);
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
            config.getServletContext());
  }

  @Override
  protected void doGet(final HttpServletRequest req,
          final HttpServletResponse resp) throws ServletException, IOException {
    resp.getWriter().write(animal.sound());
  }    
}


推荐答案

此是错误的:

@Service
public class Hello extends HttpServlet {

Servlet的生命周期是由servlet容器而不是Spring控制的。因此,您无法将Spring bean直接自动连接到servlet。 Spring根本不应该创建servlet。 Spring基本上对您的servlet一无所知,它尝试实例化它,但是它与servlet容器创建的实例不同,用于处理请求。

Servlet's lifecycle is controlled by the servlet container, not by Spring. Thus you can't autowire Spring beans directly to servlet. Spring should not create servlets at all. Basically Spring doesn't know anything about your servlet, it tries to instantiate it, but it's not the same instance that was created by the servlet container and that is used to handle requests.

最后,您的servlet没有no-arg构造函数。这样的构造函数是必需的,但不会使您的示例通过。

Finally, your servlet doesn't have a no-arg constructor. Such constructor is required, but it won't make your example pass.

解决方案是直接从注册的Web应用程序上下文中获取所需的Spring bean:

The solution is to fetch desired Spring beans directly from registered web application context:

WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
Animal animal = context.getBean(Animal.class);



另请参见(其他解决方案)




  • 从JBoss中的servlet访问Spring bean

  • See also (for other solutions)

    • Access Spring beans from a servlet in JBoss
    • 这篇关于使用Spring注入的InstantiationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆