wangjie-fourth 的个人博客

记录精彩的程序人生

目录
java源代码管理
/  

java源代码管理 置顶!

一、Java的源代码管理

1、JVM与源代码
JVM在工作的时候,大致分为:

  • 执行一个类的字节码
  • 如果碰到新的类,就去加载这个新类

那么它是如何加载这个类的呢?-- 类路径【Classpath】
java在命令行启动程序的时候,会将一个classpath的环境变量传递给程序,这个环境变量值存储的是程序要使用类的路径信息。

JVM会通过全限定的类路径名称,找到要加载的类

2、java命令行启动程序
其命令如下:

java -classpath...:

classpath包含第三方jar包、自己写的代码。在这个命令参数可以找到所有要运行的类
jar包就是许多类放在一起的压缩包

3、传递性依赖
在项目中,可能会依赖第三方类,而这个第三方又依赖另一个第三方类。即:你依赖的类还依赖别的类。
image.png

4、Classpath hell
全限定类名是类的唯一标识。如果多个相同类路径出现在classpath中,我们将这种情况称为classpath hell。也称为包冲突。一般情况下,是由于项目引入多个不同版本的jar包。这样,JVM在加载类的时候,就有了俩个选择,程序的结果就会不同。

5、java源代码管理带来的几个问题
(1)jar的下载
我项目需要依赖第三方jar包,我需要在classpath中传递jar包的基本路径。这个时候,我要把jar包下载下来,放到本地下,我要去哪下载呢?
(2)classpath参数值复杂
一个项目可能需要很多jar包,如果手工在命令行拼接这些jar包路径的话,出现错误的可能性就非常大。
(3)依赖版本升级替换
在开发中,可能需要升级第三方jar包的版本,只要升级就需要在classpath找到旧版本路径,并将其删除。然后再添加新版本的jar包路径。这个过程是非常繁琐的,有很大可能出现错误。

二、源代码管理的初始时代 -- Apache Ant

手动下载jar包,放在一个目录中;
写XML配置,指定编译的源代码目录、依赖的jar包、输出目录等;
1、缺点:

  • 每个人都要自己造一套轮子
  • 依赖的第三方类库都需要手动下载,费时费力
  • 没有解决Classpath地狱的问题

三、划时代的源代码管理 -- Maven

maven做的相关约定:

<dependency>
  <groupId>org.hzero.starter</groupId>
  <artifactId>hzero-starter-export</artifactId>
  <version>0.6.0</version>
</dependency>

这里的groupId和hzero-starter-export相当于一个全限定的一个包名

  • 不允许对某个版本的包修改,只允许对包进行版本升级

1、语义化版本

程序中的版本格式x.y.z:主版本号.次版本号.修订号

  • 主版本号:做个不兼容的API的修改
  • 次版本号:做了向下兼容的功能性新增
  • 修订号:做了向下兼容的问题修正

这也是maven的0.6.0的含义。

2、SNAPSHOT快照版本

(1)用处

这些maven代码在开发得时候,可能需要频繁更新。

比如说:我自己写一个工具包,写完之后,就提交到maven仓库发版一下。但是,突然我发现一个小的错误,这个错误不值得提个版本;而maven又不允许直接修改这个版本的代码。

这个时候,就是SNAPSHOT快照版本的用处了。

快照版本的好处是:在项目协作的时候,别人引用我的包,就不必频繁更新版本号。这也是快照版本的主要用处。

3、其他功能

maven还解决了以下问题:

  • 传递性依赖的自动管理

  • 依赖冲突的解决

  • 依赖的scope

4、scope

  • compile:编译时有效,运行时也有效

  • test等

  • provided:只在编译有效,运行时无效

四、包冲突的解决

当程序出现如下异常的时候,就有可能是包冲突的问题

  • AbstractMethodError

  • NoClassDefFoundError

  • ClassNotFoundException

  • LinkageError

这其实就是classpath hell的问题。

maven对这种classpath hell[依赖冲突]进行了解决。其原则是:

  • 绝对不允许classpath出现同名但不同版本的jar包

其解决的规则是:

  • 优先选择离项目层级最近的版本

  • 层级相同时,优先选择首次加载的版本

举个例子:

(1)优先选择离项目层级最近的版本
image.png

(2)优先选择首次加载的版本
image.png

maven的包冲突解决原则在大部分的时候,是可以解决问题。但还是遇到无法解决的包冲突问题。这个时候就需要人工解决了。

maven包冲突问题

假设项目遇到如下依赖情况:
image.png

这个时候,我们需要比较C1、C2版本在出现问题地方的代码。解决过程是:

  • 比较这俩个版本库的区别,注意比较对应类和方法

  • 如果高版本拥有完整的类或方法,我们就需要让maven引入高版本的依赖

解决方法有:

(1)在项目离得最近的地方,引入需要的版本。比如:
image.png

(2)在maven配置,选择固定版本

让D依赖排除第三方依赖

<dependency>
  <groupId>com.test</groupId>
    <artifactId>test-d</artifactId>
    <version>0.1</version>
    <exclusions>
     <exclusion>
         <groupId>com.test</groupId>
            <artifactId>test-c</artifactId>
        </exclusion>
    </exclusions>
</dependency>

这样项目就自动引入B下的C2版本依赖。

五、相关工具说明

1、查看项目依赖后得信息

mvn dependency:tree

这里显示的是maven默认处理包冲突后得项目依赖信息
2、Idea的plugin插件:Maven helper
这个插件可以查看查看项目的依赖信息,可以通过图形化界面处理包冲突

3、POM

POM的全写是project object model。其意是项目对象模型,就是介绍整个项目架构信息。

评论