在一个springboot项目中,因为需求的变更,需要使用到阿里云的日志记录功能,使用的组件依赖是
<dependency>
<groupId>com.aliyun.openservices</groupId>
<artifactId>aliyun-log-logback-appender</artifactId>
<version>0.1.15</version>
</dependency>
这个组件依赖了两个组件
项目启动后报错
进入这个类之后发现果然没有这个方法,其继承的接口也同样没有这个方法。总之就是找不到。
进入阿里云的这个依赖后发现依赖有如下两个组件
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
版本很明显是1.2.3,但是查看External Libraies(如上图所示)很明显最上面的是1.1.11版本。
于是问题来了,我查看项目的依赖中,发现有,接着往下追踪,发现有,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
然后spring-boot-starter-web又依赖了
spring-boot-starter
然后spring-boot-starter 又依赖了
spring-boot-starter-logging
然后spring-boot-starter-logging又依赖了
logback-classic
然后logback-classis又依赖了
logback-core
那么版本都是1.1.11
我的问题是,按照maven依赖三个原则
a)、依赖路径最短优先原则
项目依赖了两个jar包,其中A->B->C->Y(1.0.0) , A->D->Y(2.0.0)。由于Y(2.0.0)路径最短,所以项目使用的是Y(2.0.0)。
b)、pom文件中先来后到原则
如果A-B-Y(1.0.0) ,A-C-Y(2.0.0) 即路径长度都是2,相同的情况下,maven加载的顺序是按照先后顺序,即如果先依赖了B,后依赖了C,那就最后的依赖就是最先声明的A里面的Y(1.0.0)。
c)、覆盖原则
子pom内声明的优先于父pom中的依赖。
显然上面的三个原则中的1,2两条都没有遵循,真的奇怪。
于是我又建立了一个纯maven项目,这次不是springboot项目,这个项目的依赖非常简单,依赖只有两个,如下
<dependency>
<groupId>com.aliyun.openservices</groupId>
<artifactId>aliyun-log-logback-appender</artifactId>
<version>0.1.15</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>
哈哈,这一次我发现maven的依赖原则都是严格遵循的,如图:
如果我手动exclud,那么也是可以正确引入想要的依赖版本
那么问题来了,为什么在springboot的项目里面,始终是不能按照规则来呢。
仔细查看发现springboot项目里面有个<parent>标签,那么我在这个纯的maven项目也引入springboot的parent看看是什么效果呢
看,又变成了1.1.11了。看起来还真是这个parent搞的鬼,进入这parent,发现他还有parent,是
spring-boot-dependencies
再向上追溯,发现有
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
此时的版本号码是
<logback.version>1.1.11</logback.version>
那么此时得出的结论是,其实还是遵循了maven依赖的版本原则,因为parent的路径也是1,阿里云的路径也是1,相同路径情况下,parent引入的顺序是优先于阿里云的,所以,版本也就是1.1.1了。
那么实际项目中我还是必须使用1.2.3这个版本,不然就启动就报错了,那么按照第三种覆盖原则,我只能在此项目中直接指定这个logback的依赖了,即直接引入
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
至此,问题得以解决,同时加深了对maven的印象