有两款产品上的很急,所以就按照之前同事写的方法写了接口,妈的居然是servlet,so old……
之前调试的好好的,啥问题没有,然后我神操作了一番,一共有两个servlet,当我访问第一个servlet再访问第二个servlet的时候,但是我这个访问顺序颠倒过来的时候……
结果突然遇到了一个让人疯狂的问题:
Error creating bean with name 'tecHolderService': Bean with name 'tecHolderService' has been injected into other beans [zhlhService] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:423)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:749)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:704)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:416)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:642)
at com.sinosoft.httpservlet.ZHLHServlet.getBackXml(ZHLHServlet.java:192)
at com.sinosoft.httpservlet.ZHLHServlet.service(ZHLHServlet.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
看样子貌似意思是在说不能循环注入
看了一下applicationContext.xml中架构了AspectJ,估计它的意思就是嫌弃Spring自己的AOP不好用呗,所以用AspectJ,那就把这段配置注释掉吧,老子不用AspectJ了
果然注释掉以后就好了,没问题了。
原因就是当用了AspectJ的时候,Spring的循环注入就不能用了。
这玩意治标不治本啊,咋办?这么大个项目谁知道里面哪块用到了AspectJ了?
更蛋疼的是让我发现了servlet里面的service方法,里面的对象我是配的Spring bean然后setter/getter方法注入的,第一次访问数据的时候正常都能跑,但是你接着再跑的时候你把对象里面的东西打印出来发现居然是上一次保留下来的数据!
WTF?!
继续想想咋办吧
然后我就发现一个问题:
跟别的配的bean不太一样,原来是这样的:
对,就是少了 scope="prototype"
然后我就把没配scope="prototype"的bean都配上了
然后再按照原来的方式操作
Bingo~
原来你不配scope="prototype"的时候Spring默认是单例模式的,也就是只创建一个Action对象,这样数据不安全,配了这个东西就会保证当有请求的时候都会创建一个Action对象,不然你前一次访问提交的数据还是会保留下来。
spring 默认scope 是单例模式
这样只会创建一个Action对象
每次访问都是同一个Action对象,数据不安全
struts2 是要求 每次次访问 都对应不同的Action
scope="prototype" 可以保证 当有请求的时候 都创建一个Action对象
而且servlet的生命周期的原理,很!重!要!(此处敲黑板)
servlet只会被创建一次,所以千万不要在servlet里面定义任何东西,方法里除外。单机访问肯定没问题啊,你开个多线程你试试?