Spring在注入参数时尝试实例化接口

ahp*_*ete 0 spring spring-mvc

我希望你能帮助我.

我在我的Web应用程序中使用Spring MVC(3.1.1),并且面临着一种奇怪的情况.我有这个简单的@Controller,它使用ServicioUsuario服务,并且工作正常:

@Controller
@RequestMapping("/ajax")
public class ControladorAjax extends ControladorGenerico {

  @Autowired
  ServicioUsuario servicioUsuario;

  @RequestMapping("/check")
  public ResponseEntity<String> check(@RequestParam String email) {
    // Declarations and other operations omitted...
    // Use servicioUsuario
    servicioUsuario.doStuff();
    return response;
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我删除@Autowiring,并尝试将Spring inject servicioUsuario作为参数(即通过将方法签名更改为:),public ResponseEntity<String> check(@RequestParam String email, ServicioUsuario servicioUsuario)整个事情就会中断,我在Tomcat的日志中得到了这种异常:

javax.servlet.ServletException: NestedServletException in java.lang.Thread.getStackTrace:: Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.package.ServicioUsuario]: Specified class is an interface
Run Code Online (Sandbox Code Playgroud)

我有这些接口:

com.package
  |-> Servicio.java (interface)
  |-> ServicioUsuario.java (interface that extends Servicio)
Run Code Online (Sandbox Code Playgroud)

这些条款:

com.package.impl
  |-> ServicioImpl.java (implements Servicio)
  |-> ServicioUsuarioImpl.java (@Service("servicioUsuario") that extends ServicioImpl implements ServicioUsuario)
Run Code Online (Sandbox Code Playgroud)

并配置Spring以扫描两个包:

<context:component-scan base-package="com.package
                                      com.package.impl" />
Run Code Online (Sandbox Code Playgroud)

为什么Spring试图实例化接口而不是实现类?这是我做错的事吗?

Tom*_*icz 5

根据官方文档的16.3.3.1支持的方法参数类型,这是控制器方法可以采用的完整列表:

  • 请求或响应对象(Servlet API).[...]例如ServletRequestHttpServletRequest.

  • 会话对象(Servlet API):类型HttpSession.

  • org.springframework.web.context.request.WebRequestorg.springframework.web.context.request.NativeWebRequest.

  • java.util.Locale 对于当前请求区域[...]

  • java.io.InputStream/ java.io.Reader用于访问请求的内容.[...]

  • java.io.OutputStream/ java.io.Writer用于生成响应的内容.[...]

  • java.security.Principal 包含当前经过身份验证的用户.

  • @PathVariable用于访问URI模板变量的带注释的参数.[...]

  • @RequestParam用于访问特定Servlet请求参数的带注释参数.[...]

  • @RequestHeader用于访问特定Servlet请求HTTP标头的带注释参数.[...]

  • @RequestBody用于访问HTTP请求主体的带注释的参数.[...]

  • @RequestPart用于访问"multipart/form-data"请求部分内容的带注释参数.[...]

  • HttpEntity<?>用于访问Servlet请求HTTP标头和内容的参数.[...]

  • java.util.Map/ org.springframework.ui.Model/ org.springframework.ui.ModelMap[...]

  • org.springframework.web.servlet.mvc.support.RedirectAttributes [...]

  • 命令或表单对象将请求参数绑定到bean属性(通过setter)或直接绑定到字段,[...]

  • org.springframework.validation.Errors/ org.springframework.validation.BindingResult[...]

  • org.springframework.web.bind.support.SessionStatus [...]

  • org.springframework.web.util.UriComponentsBuilder [...]

正如您所看到的,Spring bean不在此(非常令人印象深刻)列表中.为什么要通过控制器方法注入服务?他们从不改变.只需注入一次并将它们分配到一个字段就足够了.