天天看點

【開發筆記】Spring MVC架構更新錯誤:找不到ReflectionUtils.doWithLocalFields方法問題分析發現解決

問題

在更新Spring MVC項目版本(目标版本是4.3.16)後,啟動Tomcat輸出如下錯誤資訊:

ERROR | Context initialization failed
java.lang.NoSuchMethodError: org.springframework.util.ReflectionUtils.doWithLocalFields(Ljava/lang/Class;Lorg/springframework/util/ReflectionUtils$FieldCallback;)V
	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.buildPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:418)
	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:397)
	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:333)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:929)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:220)
	at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:619)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:465)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4745)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5207)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
           

分析

通過搜尋【doWithLocalFields java.lang.NoSuchMethodError】,得到類似的條目有:

(1)https://stackoverflow.com/questions/46056321/spring-java-lang-nosuchmethoderror-org-springframework-util-reflectionutils-dow

(2)https://www.cnblogs.com/sxdcgaq8080/p/8022121.html(參考(1)中的結論:4.2以後上面報錯的方法就被提到了spring-core架包中而不是在orm架包中,是以,需要将spring-orm架包的版本降低到<4.2以下)

(3)https://bbs.csdn.net/topics/392078670?page=1(僅提問,未解決)

搜到的條目并不是很多,看來并不是很多開發者傾向于更新架構版本(雖然最新的Spring架構版本都到了5.0+)。

雖然看完(1)和(2)感覺結論并不靠譜,并不會是4.2版本這個梗。

顯而易見,架構是整體的,不可能就其中的某一個jar包為低版本吧?!

即便這樣,(3)中的一個操作點醒了我,決定檢視一下這個工具類的定義看看。

發現

在eclipse中使用快捷鍵Ctrl+Shift+t,檢索ReflectionUtils這個工具類的引用,結果是大吃一驚!

【開發筆記】Spring MVC架構更新錯誤:找不到ReflectionUtils.doWithLocalFields方法問題分析發現解決

如上圖,居然發現有2個該類的定義!其中1個類定義居然在Active MQ的jar包中!

再搜尋doWithLocalFields ActiveMQ,得到類似的條目:

(1)https://www.oschina.net/question/2670896_2242950(但沒有得到解決方法)

問題定位在ActiveMQ的jar包中,打開該jar包,果不其然:

【開發筆記】Spring MVC架構更新錯誤:找不到ReflectionUtils.doWithLocalFields方法問題分析發現解決

頓時有2個疑問:

(1)為啥ActiveMQ的jar包中包含了Spring架構的代碼?

(2)為啥舊版的ActiveMQ的jar包沒有出現這個問題?

在ActiveMQ的官網上(http://activemq.apache.org/)似乎找到了根源:

從5.12.0版本開始,ActiveMQ的jar包中開始包含spring架構的部分代碼(部分工具類),其中的代碼是否與Spring官方釋出的代碼是否同步就不由得知了。

解決

使用ActiveMQ的5.12版之前的最後版本(5.11.4)替換較新5.14.5版本。

總結

(1)該問題屬于jar包沖突的問題

(2)對于(1)需要進一步了解沖突類/接口的定義、引用情況,記住使用快捷鍵Ctrl+Shift+t

(3)不要一口氣全部替換,可以分步替換,這樣可以快速定位。

繼續閱讀