Spring是如何使用Java8类的,但它运行在Java7上的?
我最近下载了Spring框架中Spring MVC(版本4.0.2.RELEASE)模块的源代码。我的意图是针对模块的实际源代码而不是实际的.jar
文件运行。(说来话长,仅用于测试目的)
下载源代码后,我从我的项目中删除了jar
文件,编译并部署到服务器上。当我点击dispatcher servlet处理的一个URL时,出现了一个错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0': Invocation of init method failed; nested exception is java.lang.Error: Unresolved compilation problems:
The import java.time cannot be resolved
The method toZoneId() is undefined for the type TimeZone
ZoneId cannot be resolved
经过一些研究和对源代码的挖掘,我意识到错误中提到的类是JDK/JRE 1.8的一部分。在删除.jar
文件之前,我的项目在JDK/JRE 1.7上运行时没有问题
我的问题是Spring如何包含来自JDK 1.8的类,但仍然能够在JDK/JRE 1.7下运行?为什么在使用Spring的.jar
文件时不会抛出异常,但在我提供源代码时(jar文件丢失)会抛出异常
完整堆栈跟踪
Mar 26, 2014 7:27:18 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Allocate exception for servlet dispatcher
java.lang.Error: Unresolved compilation problems:
The import java.time cannot be resolved
The method toZoneId() is undefined for the type TimeZone
ZoneId cannot be resolved
at org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver.<init>(ServletRequestMethodArgumentResolver.java:23)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.getDefaultArgumentResolvers(RequestMappingHandlerAdapter.java:522)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.afterPropertiesSet(RequestMappingHandlerAdapter.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:624)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:672)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:543)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1274)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1186)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:858)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:136)
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.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
# 1 楼答案
标题问题的答案是:Spring使用Java8构建,但与Java7(和6)兼容
ServletRequestMethodArgumentResolver
确实导入了java.time.ZoneId
,但它只引用嵌套类中的那个类,除非Java 8位于类路径上,否则该类不会被实例化。Spring源代码中有很多这样的例子(一直都是,例如,自从它开始支持Java5以来)