maven工程在导入jar包时,就必须要考虑解决jar包冲突问题。
maven导入jar包时候,我们只需要导入一个主要的包,那么它所依赖的其他jar包也会自动带入到项目中。比如现在导入一个spring-context包,版本5.0.7。
在图左边是进入项目中的jar包,除了spring-context包外,其他都是maven自动导进来的。这是maven提供的一个非常的功能,但是它也存在着问题。
假如现在再导入一个4.1.7版本的spring-beans包。在idea中看一下现在项目中jar包依赖关系图,点击右侧maven project,再点击图中圈着按钮即可打开。
项目中直接导入了context和beans两个jar包。从图中可以看到,beans依赖着spring-core,而context这边往上找也能找到spring-core包。也就是说两个包同时依赖着core包,只是一个版本是5.0.7,另一个版本则是4.1.7。此时就出现了jar包冲突的问题。
假如我是想要4.1.7这个版本,可以怎么做?
现在先看一下现在项目的jar包信息。
beans包是4.1.7版本,而core包是5.0.7版本,也就是说core包的版本没有变化。
现在把context和beans两个包换一下位置,beans放在context上面,不改它们的版本。再看一下core包的版本:
此时已经改为4.1.7版本。
也就是说两个jar包的坐标没有改变,但是导入的顺序不同,最终进入项目的依赖也不一样。
这是因为maven的第一声明原则,即哪个jar坐标在上面的,这个jar就是先声明。先声明的jar包坐标下的依赖包,可以优先进入项目中。这是解决jar冲突的第一种方式。
现在看第二种方式
先理解两个概念:
直接依赖:项目中直接导入的jar包,就是该项目的直接依赖包。如项目的context和beans包就是直接依赖包。
传递依赖:项目中没有直接导入的jar包,可以通过项目直接依赖jar包传递到项目中,如项目中的spring-core包。
假设我们需要4.2.4这个版本的spring-core包,我们直接导入
已经是4.2.4版本。
所以解决冲突的第二种方式就是:路径近者优先原则。直接依赖路径比传递依赖路径近,那么最终进入项目的jar包会是路径近的直接依赖包。
假如core包要和context一样使用5.0.7版本,现在beans声明在前,版本是4.1.7,如果不使用第一和第二种方式,还可以怎么做?
那就是使用exclusions排除,里面可以放置很多个exclusion,每个里面只需要填groupId和artifactId。
在beans这个依赖里面排除spring-core,可以达到效果:
所以解决jar包冲突的方式三:使用直接排除。当我们要排除某个jar包下的依赖包时,在配置exclusions标签的时候,内部可以不写版本号。因为此时依赖包使用的版本默认和本jar包一样。
所以,只要今后你的是maven工程,在导入jar包的时候,可以根据以上三种方式解决jar冲突,推荐使用第三种,即使用exclusions来排除。因为这种方式更加直接和清楚,如果使用其他的方式也可以,但有可能造成项目里面jar版本混乱。版本的改变有可能造成功能不稳定,所以说我们要避免这种情况。
像我们在公司的项目中依赖着很多jar包,假如需要开发一个新功能,要导入新的jar包,此时就要看一下这个jar包的依赖,会不会影响其原有的jar包,有的话就排除掉。