Servlet不能經過Spring依賴注入

在今天這個特殊的日子裏(雙十一)要在本身的項目中對外暴露一個接口,供其餘程序進行訪問,使用的是一個統一的Servlet對外來暴露接口,可是出現了一個很棘手的問題,那就是在Tomcat服務起來以後,在瀏覽器進行訪問的時候,報一個500的錯誤!讓我真的很費解,錯誤以下:java

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

type Exception reportspring

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

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

exceptiontomcat

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)mvc

而後開始上網進行瘋狂的查找,找了半天,不少都是說web.xml中servlet-class配置的不對,沒有含有包名,或者是包名錯誤致使的,可是個人包名確實是正確的。app

可是在最後我發現了個人代碼中引用的一個service相比於其餘代碼,是採用Spring依賴注入的方式注入的,代碼以下:this

@Resource(name="testservice")url

private Testservice testservice;

而後,將這段代碼去掉,採用getBean的方式進行的獲取,哇,居然能夠了。

替換方式:

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

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

接着就上網查詢這是爲啥呢?結果緣由以下:

 Spring不能經過註解向Servlet中注入實例的原理

        想了解此問題的原理,就要了解tomcat啓動後 servlet和spring的加載順訊。

      一、  tomcat啓動後先加載web.xml文件。web.xml主要配置了servlet 、filter、listenner三種javaee規範的類,加載順序跟在web.xml文檔

中的位置無關。  順序爲  listenner>filter>servlet 。

二、而spring的初始化類爲org.springframework.web.context.ContextLoaderListener,就是一個listenner,它是先於servlet加載的。普通servlet和springmvc的入口servlet

的加載順序,就要看servle的設置了。

       三、在 servlet A類上加@service或@controllert等註解時,spring或springmvc會掃面相關包,自動實例化一個servlet 實例A;這個實例A的引用是spring容器管理的。

       四、固然 servlet也會在web.xml配置(要否則怎麼攔截url),這是tomcat容器會根據servler配置啓動時或者第一次請求該url時實例化該servlet 實例B,

這個實例B的引用是tomcat容器管理的。

      五、明白了吧,攔截url的servlet和spring依賴注入的servlet不是同一個實例!!因此就產生了不能依賴注入或者註解不起做用的現象。

也就是說Spring管理普通的JavaBean還好,servlet 和filter最後不要使用依賴注入,本身獲取最好。

相關文章
相關標籤/搜索