Welcome everyone

maven 依赖概述

java 汪明鑫 861浏览 0评论

依赖

依赖到底是什么

依赖就可以理解为jar包/war包

 

多模块项目的父pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>common</module>
        <module>web</module>
        <module>service</module>
        <module>db</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>pers.wmx</groupId>
    <artifactId>daily-coding</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>daily-coding</name>
    <description>daily-coding</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <java.version>1.8</java.version>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>

        <mybatis_spring_version>1.3.1</mybatis_spring_version>

        <lombok.version>1.16.20</lombok.version>
        <fastjson_version>1.2.57</fastjson_version>
    </properties>

    <dependencyManagement>
        <!-- 项目全局的依赖版本管理,所有依赖的版本号必须定义在这里 -->
        <dependencies>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>

            <!-- 所有子模块的版本保持一致 -->
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>web</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>service</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>common</artifactId>
                <version>${project.version}</version>
            </dependency>

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis_spring_version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson_version}</version>
            </dependency>

        </dependencies>

    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 

整个项目的依赖和其版本号都在父pom中管理起来,儿子需要什么就拿什么,不用管版本号

dependencyManagement顾名思义,就是依赖的管理者

dependency 就是具体的依赖,这些依赖的groupIdartifactIdversion依赖的基本坐标,都可以在maven中央仓库查寻。

一般习惯于在properties 定义版本号,在dependency直接引用,就好像声明变量似的

 

依赖范围

依赖又有范围scope

依赖范围就是用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系

 

a) compile  编译(默认)

编译依赖范围

对编译classpath、测试classpath、运行classpath都有效

 

b) test

测试依赖范围

测试classpath有效

 

c) provided 编译
provided依赖只有在当JDK或者一个容器已提供该依赖之后才使用, provided依赖在编译和测试时需要,在运行时不需要,比如:servlet api被tomcat容器提供。

 

d) runtime 运行、测试时,编译时不需要,如jdbc驱动包

 

e) system 本地一些jar
显示指定依赖文件路径,不可移植,慎用

 

f)import

导入依赖范围

不会对三种classpath产生实际影响

 

Dependency scope 是用来限制Dependency的作用范围的, 影响maven项目在各个生命周期时导入的package的状态。

依赖范围由强到弱的顺序是:compile>provided>runtime>test

 

 默认引入 的jar包 ——- compile 【默认范围 可以不写】(编译、测试、运行 都有效 )

servlet-api 、jsp-api ——- provided (编译、测试 有效, 运行时无效 防止和tomcat下jar冲突,容器已经提供)

jdbc驱动jar包 —- runtime (测试、运行 有效 )

junit —– test (测试有效)

 

maven仓库

https://mvnrepository.com/

在这里基本都能找到你需要的依赖,神器

 

 

依赖传递

 

但是也有一定的条件:

 

maven会解析各个直接依赖的pom,将那些必要的间接依赖以传递性依赖的形式引入到当前项目

依赖范围还会影响传递性依赖

 

更详细的见下表

第一直接依赖 \ 第二直接依赖

compile

test

provided

runtime

compile

compile

——

——

runtime

test

test

——

——

test

provided

provided

——

provided

provided

runtime

runtime

——

——

runtime

最左一列表示第一直接依赖的范围,最上一行表示第二直接的范围

交叉的节点得到的就是间接依赖的范围

 

 

依赖仲裁

首先严禁在同一个pom中声明两个不同版本的依赖

然后我们看下下面两个基本的依赖原则:

 

  • 最短路径原则

A–>B–>C–>X(1.0)、A–>D–>X(2.0),X(1.0)的路径长度为3,而X(2.0)的路径长度为2,因此X(2.0)会被解析使用

 

  • 加载先后原则

A–>B–>Y(1.0),A–>C–>Y(2.0),Y(1.0)和Y(2.0)的依赖路径长度是一样的,都为2

第一声明者优先。在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用。顺序最靠前的那个依赖优胜。

 

如:

 

这样按照一些规则加载依赖,就不会产生冲突和问题

 

可选依赖

如果A依赖B,B可选依赖C(optional),则C对A是不可见的

 

A的pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>A</groupId>
    <artifactId>A</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9.9</version>
        </dependency>
    </dependencies>
</project>

 

B的pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>B</groupId>
    <artifactId>B</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>A</groupId>
            <artifactId>A</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

joda-time 对B是不可见的,可再显示引入依赖

 

排除依赖

maven解析后的依赖中,不可能出现groupId和artifactId相同,但是version不同的的两个依赖

 

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion> 
          <groupId>sample.ProjectC</groupId>
          <artifactId>Project-C</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
  </dependencies>
</project>

项目A在引入对项目B的依赖时,排除了对项目C的依赖。

但并不影响项目A在其他地方引入对项目C的依赖。

例如,项目A又引入了对项目D的依赖,而项目D依赖项目C,这个时候,项目A就又产生了对项目C的依赖。

或者项目A直接显示声明对C的其他版本依赖

 

排除依赖我觉得主要原因

一来是解决依赖冲突

二来是排除掉不稳定的版本,自己引入需要的版本

 

 

 

依赖排查命令

mvn dependency:list
mvn dependency:tree
mvn dependency:analyze

 

参考

https://www.cnblogs.com/LaiCuiTing/p/9542525.html

https://www.52xbc.cn/java/301.html

《Maven实战》 (这本书正在看,真心不错!)

转载请注明:汪明鑫的个人博客 » maven 依赖概述

喜欢 (0)

说点什么

您将是第一位评论人!

提醒
avatar
wpDiscuz