背景介紹,項目通過maven來管理,有項目依賴關系,使用eclipse的springSource tool suite來編譯
項目在執行junit測試時報如下錯誤:
Exception in thread "main" java.lang.NoSuchMethodError: org.springframework.beans.factory.annotation.InjectionMetadata.<init>(Ljava/lang/Class;)V
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:318)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:277)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:798)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:493)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:880)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:596)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:365)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at TestSpring.main(TestSpring.java:12)
分析:找不到InjectionMetadata的構造函數(Ljava/lang/Class;)
查看InjectionMetadata方法聲明,項目中maven使用spring3.0
spring2.5構造函數:InjectionMetadata(Class targetClass)
spring3.0構造函數:InjectionMetadata(Class<?> targetClass, Collection<InjectionMetadata.InjectedElement> elements)
錯誤原因很清楚:spring-context.jar的版本使用的2,調用InjectionMetadata的構造函數(Ljava/lang/Class;),問題是spring-context.jar的2版本eclipse從哪找的
查看了pom.xml依賴關系圖,未找到引用spring2版本
查找項目依賴的mavenlib包也沒有spring2相關jar
為了防止是Junit造成,改用main函數調用,錯誤依然
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
}
用類的加載順序先於jar包,強制版本
直接在項目的源代碼中加入spring的CommonAnnotationBeanPostProcessor類源代碼,根據類的加載順序會加載本類,確實不報找不到方法了。
小插曲:CommonAnnotationBeanPostProcessor中有引用 import javax.ejb.EJB;懷疑是不是因為沒有javax.ejb.EJB相關jar包引起的,如果是因為沒有javax.ejb.EJB相關jar,那tomcat下為什么能正常引用,除非tomcat下有相關jar包,后來從tomcat下找到apache-tomcat-6.0.26\lib\annotations-api.jar,把annotations-api.jar引用eclipse編譯路徑下,CommonAnnotationBeanPostProcessor不報錯了,但刪除CommonAnnotationBeanPostProcessor類,錯誤依然。說明還是存在jar包沖突。
還說明一個java語言的一個規定:如果加載的Class文件中引用了不存在的其它類,是可以正常加載的,除非調用了相關方法才會報錯。這只是個小插曲,和錯誤原因無關。
刪除所有依賴,全部手工加載外部jar
改動前
改動后,jar包從maven編譯完后的target下取得
沒有錯誤了,通過試錯,最終發現是因為 Web App Libraries造成的問題
附上 Web App Libraries的具體內容:
最終原因分析:eclipse的 Web App Libraries和maven的編譯機制存在差異
在maven體系中:通過在maven中認為無依賴的可能會通過Web App Libraries最終達到eclipse的編譯路徑中。
只要對應的項目處理打開有狀態中,如果關閉dao項目,就不會報錯。只要打開依賴的項目,maven中的exclusions對於eclipse是失效的。