当接口作为参数提供时,java依赖项注入不起作用
这是我的控制器类
@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)
但是在直接传递实现类即MyTestImpl时,它工作得很好
@RequestMapping("/")
public String home(MyTestImpl test){
test.draw();
return "homePage";
}
如果出现接口,请在此说明异常原因。 下面是MyTest实现类
@Component
public class MyTestImpl implements MyTest{
@Override
public void draw() {
System.out.println("inside test");
}
}
春天。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>
# 1 楼答案
是您的组件扫描值覆盖接口所在的包。使用@Autowired注释进行注射
# 2 楼答案
你所做的是正确的,只是你需要告诉Spring如何反序列化你的接口(也就是说,需要哪个具体的类实现)
另外,假设您正在使用Post方法,请将控制器更改为:
(“products”参数当然可以是text/html或您返回的任何内容)
# 3 楼答案
首先,我想指出,你们混合了不同的术语
如前所述,自动布线是spring的核心概念。如前所述,@Autowire应该在setters上完成,对于非配置bean*,下面是相关的短语:
其次,这里您试图将bean(@Component)注入到MVC控制器中,更具体地说,是注入bean的接口
如果仔细查看文档(here),您会发现Spring支持各种参数,并且会尽可能地将它们传递给控制器方法
这里的问题是,Spring无法知道将什么传递给您的方法。 当调用控制器时,spring将看到这个参数属于最后一类,即^{:
如果一个方法参数与上述任何一个参数都不匹配,默认情况下,如果它是由BeanUtils#isSimpleProperty确定的简单类型,它将被解析为@RequestParam,否则将被解析为@ModelAttribute
现在,根据您的问题,您可以:
作为@Controller的成员自动连接bean或接口,例如:
或者将您的实现传递给您的方法控制器
# 4 楼答案
你这样做是完全错误的。这是一个工作代码
用
@RequestMapping
注释的方法的参数应该/将以Pathvariable或RequestParams的形式出现,或者仅以HttpServletRequest对象本身的形式出现。这不是自动关联实例的方式依赖项注入在构造函数、字段和接口级别工作。不在方法参数级别。希望一切都清楚