您的位置:首页 > 编程语言 > Java开发

Servlet不能通过Spring依赖注入

2017-11-11 00:00 357 查看
摘要: Servlet不能通过Spring依赖注入

在今天这个特殊的日子里(双十一)要在自己的项目中对外暴露一个接口,供其他程序进行访问,使用的是一个统一的Servlet对外来暴露接口,但是出现了一个很棘手的问题,那就是在Tomcat服务起来之后,在浏览器进行访问的时候,报一个500的错误!让我真的很费解,错误如下:

HTTP Status 500 - Error instantiating servlet class com.hr.rmi.RemoteServiceServlet

type Exception report

message Error instantiating servlet class com.hr.rmi.RemoteServiceServlet

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException:Errorinstantiatingservlet class com.yinker.hr.rmi.RemoteServiceServlet org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 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:1023) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) java.util.concurrent.ThreadPoolExecutor.runWorker(UnknownSource) java.util.concurrent.ThreadPoolExecutor$Worker.run(UnknownSource) java.lang.Thread.run(UnknownSource)root causejavax.naming.NamingException:Cannotcreateresourceinstance org.apache.naming.factory.ResourceEnvFactory.getObjectInstance(ResourceEnvFactory.java:117) javax.naming.spi.NamingManager.getObjectInstance(UnknownSource) org.apache.naming.NamingContext.lookup(NamingContext.java:843) org.apache.naming.NamingContext.lookup(NamingContext.java:168) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 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:1023) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) java.util.concurrent.ThreadPoolExecutor.runWorker(UnknownSource) java.util.concurrent.ThreadPoolExecutor$Worker.run(UnknownSource) java.lang.Thread.run(Unknown Source)

然后开始上网进行疯狂的查找,找了半天,很多都是说web.xml中servlet-class配置的不对,没有含有包名,或者是包名错误导致的,但是我的包名确实是正确的。

但是在最后我发现了我的代码中引用的一个service相比于其他代码,是采用Spring依赖注入的方式注入的,代码如下:

@Resource(name="testservice")

private Testservice testservice;

然后,将这段代码去掉,采用getBean的方式进行的获取,哇,竟然可以了。

替换方式:

WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

this.fileResourceService=applicationContext.getBean("testservice", testservice.class);

接着就上网查询这是为啥呢?结果原因如下:

Spring不能通过注解向Servlet中注入实例的原理

想了解此问题的原理,就要了解tomcat启动后 servlet和spring的加载顺讯。

1、 tomcat启动后先加载web.xml文件。web.xml主要配置了servlet 、filter、listenner三种javaee规范的类,加载顺序跟在web.xml文档

中的位置无关。 顺序为 listenner>filter>servlet 。

2、而spring的初始化类为org.springframework.web.context.ContextLoaderListener,就是一个listenner,它是先于servlet加载的。普通servlet和springmvc的入口servlet

的加载顺序,就要看servle的设置了。

3、在 servlet A类上加@service或@controllert等注解时,spring或springmvc会扫面相关包,自动实例化一个servlet 实例A;这个实例A的引用是spring容器管理的。

4、当然 servlet也会在web.xml配置(要不然怎么拦截url),这是tomcat容器会根据servler配置启动时或者第一次请求该url时实例化该servlet 实例B,

这个实例B的引用是tomcat容器管理的。

5、明白了吧,拦截url的servlet和spring依赖注入的servlet不是同一个实例!!所以就产生了不能依赖注入或者注解不起作用的现象。

也就是说Spring管理普通的JavaBean还好,servlet 和filter最后不要使用依赖注入,自己获取最好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息