Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当接口作为参数提供时,依赖项注入不起作用_Java_Spring - Fatal编程技术网

Java 当接口作为参数提供时,依赖项注入不起作用

Java 当接口作为参数提供时,依赖项注入不起作用,java,spring,Java,Spring,这是我的控制器类 @Controller public class HomeController{ @RequestMapping("/") public String home(MyTest test){ test.draw(); return "homePage"; } } 在将MyTest(接口)作为参数传递给home方法时,Spring不会注入其实现类,而是抛出异常 SEVERE: Servlet.service() for s

这是我的控制器类

@Controller
public class HomeController{

    @RequestMapping("/")
    public String home(MyTest test){
        test.draw();
        return "homePage";
    }
}
在将MyTest(接口)作为参数传递给home方法时,Spring不会注入其实现类,而是抛出异常

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/spring-mvc-demo] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface com.managers.MyTest] with root cause
java.lang.NoSuchMethodException: com.managers.MyTest.<init>()
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.getDeclaredConstructor(Unknown Source)
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:209)
    at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:84)
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:132)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1686)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
如果出现接口,请在此说明异常原因。 下面是MyTest实现类

@Component
public class MyTestImpl implements MyTest{

    @Override
    public void draw() {
        System.out.println("inside test");

    }
}
Spring.xml

<context:component-scan base-package="com.controllers,com.ManagerImpl" />
    <mvc:annotation-driven/>
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>


是您的组件扫描值覆盖接口所在的包。使用@Autowired注释进行注射。

你这样做完全是错误的。这是一个工作代码

@Controller
public class HomeController{
  private final MyTest test;

   @Autowired
   public HomeController(MyTest test) {
      this.test = test;
   }

   @RequestMapping("/")
   public String home(){
      test.draw();
      return "homePage";
   }
}
@RequestMapping
注释的方法的参数应该/将以Pathvariable或RequestParams的形式出现,或者仅以HttpServletRequest对象本身的形式出现。这不是自动关联实例的方式


依赖项注入在构造函数、字段和接口级别工作。不在方法参数级别。希望它是清楚的。

首先,我想指出的是,你们混合了不同的术语

如前所述,自动布线是spring的核心概念。如前所述,对于非配置bean*,应在设置器上执行,以下是相关短语:

将构造函数、字段、setter方法或config方法标记为由Spring的依赖项注入工具自动连接

其次,这里您试图将一个bean(@Component)注入到MVC控制器中,更具体地说,是一个bean的接口

如果仔细查看文档(),您会发现Spring支持各种参数,并会尽可能将它们传递给控制器方法

这里的问题是Spring无法知道将什么传递给您的方法。 调用控制器时,spring将看到此参数属于最后一类,即
任何其他参数

如果方法参数与上述任何参数不匹配,则默认情况下,如果它是由确定的简单类型,则将其解析为@RequestParam,否则将其解析为@ModelAttribute。

因此,Spring会将其视为@模型属性,但它无法知道如何映射它,因为接口不能被实例化,因此您的错误。

现在,根据您的问题,您可以:

作为@Controller的成员自动连接bean或接口,例如:

@Controller
public class HomeController{

    //might need @Qualifier if more than one implementation
    @Autowire
    private MyTest test; 

    @RequestMapping("/")
    public String home(){
        test.draw();
        return "homePage";
    }
}
或者将实现传递给方法控制器

*尽管我在spring文档中没有发现任何明确说明什么是配置方法的内容,但我很确定这不适用于@Controller方法


您所做的是正确的,只是您需要告诉Spring如何反序列化您的接口(即预期的具体类实现)

    @JsonDeserialize(as=MyTestImpl.class)
    public interface MyTest  {
    ...
另外,假设您正在使用Post方法,请将控制器更改为:

@PostMapping(value = "/",
            consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String home(MyTest test){
        test.draw();
        return "homePage";
    }

(“products”参数当然可以是text/html或您返回的任何内容)

使用带有接口名称的@Autowired。在方法上添加@Autowired也不起作用,它会引发相同的异常。您是否将接口保留在包com.ManagerImpl中。在小写情况下,包还应该做一件事。是的,这很好。但我只是在玩。我想知道我的代码不起作用的原因。:)是的,但是根据Spring文档,您也可以将@Autowired注释应用于具有任意名称和/或多个参数的方法,并且自动连接任何方法都可以很好地工作。您能给我一个链接吗?这不是DI问题,而是序列化问题。(我猜这个问题有误)。OP试图做的是正确的,只是他需要指定如何序列化接口。在接口中,应该添加注释“@JsonDeserialize(as=MyTestImpl.class)”。粗体的注释完美地回答了这个问题。但要澄清的是:当您执行
MyTestImpl
时,该bean不会自动连接到这里。Spring MVC只是在创建它的一个新实例,因为它认为你正在使用它作为一个模型。我明白了,但仍然是这样“第二,你试图将一个bean(@Component)注入到MVC控制器中,更具体地说,是这样一个bean的一个接口”这一点不清楚,如果我很傻的话,对不起,控制器也是bean,所以依赖注入应该在这里工作,就像其他bean一样。如果我把这个方法添加到我的Cotroller中,它工作得非常好@自动连线的私有void draw(MyTest test){test.draw();}@xylo注入到方法中应该只在config方法中完成。这不是弹簧控制器应该如何使用的。您应该在字段成员或其setter上使用Autowired。@xylo根据进行编辑,以便与配置bean部分更相关。
@PostMapping(value = "/",
            consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String home(MyTest test){
        test.draw();
        return "homePage";
    }