一次jar包冲突的解决过程

背景介绍,项目通过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是失效的。

 

 

 

 

 

 

posted on 2013-12-19 18:48  关攀攀  阅读(7404)  评论(1编辑  收藏  举报

导航