问题描述: 因项目技术需求,项目需要在原有低版本Spring-3.2.15.RELEASE+ehcache-2.4.4(同时包含Mybatis)框架的基础上,升级到较新的版本(4.1.0.RELEASE及以上,本文所选版本为Spring-5.0.4.RELEASE)。
更新Spring相关依赖文件后,启动项目。发现项目出现:
java.lang.NoSuchMethodError: org.springframework.cache.ehcache.EhCach
eFactoryBean.setMaxEntriesLocalHeap(J)V
报错。
具体如下:
0.1. 报错详情:找不到setMaxEntriesLocalHeap(…)方法
报错相关信息如下:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.ehcache.EhCacheFactoryBean]:
Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework
.cache.ehcache.EhCacheFactoryBean.setMaxEntriesLocalHeap(J)V
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy
.instantiate(SimpleInstantiationStrategy.java:89)
at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1086)
... 192 more
Caused by: java.lang.NoSuchMethodError: org.springframework.cache.ehcache.EhCach
eFactoryBean.setMaxEntriesLocalHeap(J)V
at org.springframework.cache.ehcache.EhCacheFactoryBean.<init>(EhCacheFa
ctoryBean.java:101)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstruct
orAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:1
47)
... 194 more
从报错信息提示来看,大意是说在org.springframework
.cache.ehcache.EhCacheFactoryBean这个引用类下,使用了**setMaxEntriesLocalHeap(…)**方法,但这个方法在当前类中没有定义。
查阅相关网络资料发现,也有类似的少许项目出现过这样的问题,但目前暂未总结出一个有效的解决方案。而Stackoverflow上也只是提及可能因版本冲突或相关bean未定义(后续结果证明,不是这个原因):https://stackoverflow.com/questions/28167845/spring-ehcache-no-such-method-error
类似问题信息及讨论如下,这段讨论已经很接近最终的处理方案了:
0.2. 解决思路:查看报错类源码及其继承父类
在上图的讨论中有猜测说这个问题可能是Spring4.1版本的一个bug,但截至目前时间,Spring已经更新到5.0.4版本了。因此,这个问题出在Spring源码的可能性不大。
我们来查看一下报错所指的类及其相关代码:
在spring-context-support的jar包源码中,我们发现,在EhCacheFactoryBean的构造方法中,使用到了setMaxEntriesLocalHeap(10000);这一方法,而在这个类中,确实没有定义这个方法。
我们再来仔细查看整个类的全部代码,这里有一个非常重要的转折点:
在EhCacheFactoryBean这个类定义的时候,它继承了另一个类: CacheConfiguration。
问题迎刃而解:
如果EhCacheFactoryBean这个类需要使用setMaxEntriesLocalHeap(…)这一方法,那么这个方法必须定义在EhCacheFactoryBean或CacheConfiguration类之一。
从这一步可以看出,在上一图的问题讨论中,这个思路已经非常接近正确的处理方案:
0.3. 解决方案:升级ehcache-core版本,由net.sf.ehcache.config.CacheConfiguration类提供setMaxEntriesLocalHeap(…)方法
在之前配置中,项目所用的ehcache-core依赖是2.4.4版本,我们查看net.sf.ehcache.config.CacheConfiguration这个类,发现确实没有定义setMaxEntriesLocalHeap(…)方法。
因此,目前可以推出结论:
高版本Spring-EhCacheFactoryBean所需setMaxEntriesLocalHeap(…)方法需由net.sf.ehcache.config.CacheConfiguration类提供,只要找到包含setMaxEntriesLocalHeap(…)方法的较高版本ehcache-core依赖即可。
也就是说,之前报错是因为Spring升级到4.1.0及更高版本之后,ehcache-core版本相对较低,不能提供响应方法支持所致。
因此,解决这个问题,只要相应的升级ehcache-core版本即可。查看ehcache-core版本历史发现,2.5.0及以上版本均可包含setMaxEntriesLocalHeap(…)方法。
接下来修改maven:ehcache-core版本至2.6.5,再重新启动项目即正常运行!
<!-- Spring4.1及以上版本在spring-context-support.jar包需用到setMaxEntriesLocalHeap()方法,因此echcahe-core需升级到2.5.0及以上版本 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.5</version>
</dependency>