永远不要在Classpath里边放有版本冲突的jar包

总结:

BUG: 部署时报错,Spring Bean加载顺序有问题,或部分class找不到。

曾遇到:部署时,服务器上未将部分jar包删除,在一台服务器上始终无法部署成功,而另一台始终可以成功部署。

很多人都说这个问题太明显,这你还要说。虽然很明显,但是人们还是不断的犯错误。尤其是有时候侥幸心里给了人们可称之机。

只说一个web应用的例子吧。我们一般会在WEB-INF/lib目录中放自己需要的jar包。远古时代,当程序员自己手工管理这些jar包的时候,也不太会什么问题。可是有了Maven之后,程序员只是在pom.xml中申明自己需要的jar包,Maven会代劳地将这些jar包最终打在WEB-INF/lib中。再加上Maven的依赖传递、版本仲裁等牛X的机制,可以说很多程序员最后自己也不知道WEB-INF/lib下面到底打了哪些jar包的哪个版本。

如果碰巧,通过乱七八糟的依赖,你的classpath中有多个不同版本的spring的jar包。有人说:“什么?那不可能。”别急,我指得是这种情况。

 

WEB-INF/lib/spring-2.0.1.jar
WEB-INF/lib/spring-beans-2.5.4.jar
WEB-INF/lib/spring-core-2.5.4.jar

由于Maven的版本仲裁机制,我们是不可能同时有两个spring-*.*.*.jar。但是我们可以有一个spring完整的jar和两个spring modules jar包,而且他们不是同一版本的。如果版本仲裁控制的不好,这非常有可能。

然后……天下大乱了……

也许你会说,只要JVM保证每次加载的,要么一直是老版本的jar包或者地一直是新版本的jar,那就没事儿了。因为,另一个版本的jar包因了排在了classpath后边,是永远加载不到的。如果有这样的想法,那你就错了。没几天你就会崩溃的发现,JVM是一会加载老版本,一会加载新版本,有时候还混合着加载,再抛出一大堆ClassNotFoundException跟你玩。为什么会这样?

拿JBoss举例吧,JBoss说:“我是用java.io.File.listFiles()来列出来WEB-INF/lib目录下的jar包,然后严格地按顺序从前往后,一个jar包一个jar包的查找类的。”

嗯,看起来JBoss还挺严禁的。再看看Java怎么说,java.io.File.listFiles()的Javadoc说:“……There is no guarantee that the name strings in the resulting array will appear in any specific order; they are not, in particular, guaranteed to appear in alphabetical order.……”

啊?什么意思?它说它不保证返回结果的顺序?尤其是 不保证 是按文件名字典序排。也就是说好一点的情况,你在同一台机器,同一个版本的JVM上运行,没准儿每次返回的文件列表顺序还能相同。但是一旦部署到线上的机器,或者换了另一个开发环境,完全有可能listFiles()返回的文件列表顺序是不一样的。所以我们完全不能做任何关于顺序的假设。

所以,也就是说如果你的WEB-INF/lib/下面放了多个不同版本的jar包,你是完全无法控制JVM或者说JBoss去先加载哪个jar包中的类的。还是老老实实的想办法,把版本通过Maven仲裁掉。如果两部分代码确实要依赖两个不同版本的Spring,那恭喜你,发代码吧。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值