感觉很多人都理解错了, 依赖 [存储] 和 [加载] 是两回事。。
嵌套存储:
app
— m1-v1
— — m3-v1
— m2-v1
— — m1-v2
— — — m3-v2
扁平存储
app
— m1-v1
— m1-v2
— m2-v1
— m3-v1
— m3-v2
扁平存储显然是并不存在什么多版本共存的问题,而且比嵌套存储更节省那一点点存储空间的,也并不限制你打包只能加载一个模块的一个版本,有能力当然可以把 commons-lang3 的所有版本全打进 fat-jar 或 war 包里,只不过 java 的默认类加载制度的限制导致 maven 只能默认选一个它约定下的最合适的一个版本,这并不是扁平化的存储导致的。
想想如果 java 需要支持多版本 jar 包存在该如何改呢?
1. 改语法 import, 在包里面加上版本? 需要源码改动不太现实~
2. 把依赖关系带到运行时告诉类加载器,有一个类似 maven 的 pom.xml 的东西,告诉这个类依赖的版本。比如打包时直接把所有的 jar 重新打,在 META-INF 里面加上依赖描述。
3. 学 nodejs 弄目录嵌套
在 java 里面多版本共存还有许多问题,比如两个版本的同一个类在 jvm 看来是两个完全没关系的东西,假如一个接口返回这个类实例传再传给另一个接口时,虽然参数是需要这个类,传的也是,但是仅仅是因为不是同一个类加载器加载的,会报 class cast exception 的。
这是 java 的问题,不是扁平化包管理的问题。
所以大家别吐槽 maven 了,锅不在 maven~