类路径容器简介
类路径容器是一种管理项目资源的有效方法,它可以将项目资源分到一个逻辑类路径条目中。不管您是否了解它,您可能已经使用了类路径容器。最被 Java 开发人员认可的类路径容器就是 JRE System Library。每一个 Java 项目在类路径中都具有一个 JRE System Library。其他较著名的类路径容器有 JUnit 和 Plug-in Dependencies,它们都被包含在基础 Eclipse 项目中,还有 Web App Libraries 容器,它是 Web Tools Project (WTP) 的动态 Web 项目类型的组成部分。在开始实现我们自己的类路径容器之前,先来回顾一下类路径条目的各种类型。
每个 Java 项目都包含一个定义项目类路径的 .classpath 文件。通常并不手动编辑该文件,而是在用户更改项目的 Java 构建路径属性时由 JDT 插件创建和修改该文件。类路径中的每个条目都具有一个 kind
属性和一个 path
属性,以及各种其他的类型相关的可选属性。条目在文件中出现的顺序将决定它们在项目的类路径中的顺序。在继续学习之前,可以先做一个很好的练习:创建一个 Java 项目,尝试修改 Java 构建路径属性、创建条目,以及修改最初的默认条目,获得 .classpath 文件,如清单 1 所示。
清单 1. 显示所有条目类型的示例 .classpath 文件
<?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src"/> <classpathentry kind="lib" path="lib/derby.jar" sourcepath="lib/derby-src.jar"/> <classpathentry kind="var" path="ECLIPSE_HOME/startup.jar"/> <classpathentry combineaccessrules="false" kind="src" path="/bar"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="output" path="bin"/> </classpath> |
清单 1 显示了六个类路径条目,它们被标记为五种类型
。在底层 Eclipse Java 模型中,每一种都由一个 org.eclipse.jdt.core.IClasspathEntry
类型表示,该类型分为条目(entry-by-entry)类型
和目录(content)类型
。目录类型
是为大多数条目类型
定义的,它是源代码(org.eclipse.jdt.core.IPackageFragmentRoot.K_SOURCE
)或者二进制代码(IPackageFragmentRoot.K_BINARY
)。在 Eclipse V3.2 中,IClasspathEntry
接口定义了五种常量来引用类路径条目类型
,但是和清单 1 中标记的五种类型不同。事实上,清单 1 中显示的一种类型 — 即 output
— 并没有定义为 IClasspathEntry
中的常量,而另一个 — src
— 在清单 1 中显示了两次,这是因为在 IClasspathEntry
中它们被表示为不同的常量。这有些难于理解,但让我们先忽略这点,从文件的开始部分看起。
清单 1 中的第一个条目具有 kind="src"
以及 path="src"
。这表示项目具有一个源文件夹,位于项目根目录 src
下的一个目录。它暗示了项目的一些信息 — 很明显,它告诉 Java 编译器它需要编译位于 src 目录的源代码。这种条目类型是由 IClasspathEntry.CPE_SOURCE
常量表示,并具有一个 IPackageFragmentRoot.K_BINARY
的目录类型
。当创建了 Java 项目后,将从工作区首选项中继承默认的源文件夹和输出文件夹(在 Eclipse 中参见 Window > Preferences > Java > Build Path)。在最新的 Eclipse 安装中,源文件夹和输出文件夹将被设置到根项目文件夹。清单 1 中的第一个 src
条目具有一个 path="src"
是因为工作区的默认源文件夹被更改为 src。
清单 1 中的第二个条目具有 kind="lib"
和 path="lib/derby.jar"
。这表示在项目根目录下的 lib/derby.jar 中有一个二进制类路径条目。lib
条目引用了一组具有路径属性的类文件,这些路径属性指定了 .class 文件的目录或包含 .class 文件的档案文件。该条目还包含可选的 sourcepath
属性,该属性引用了源代码附件的位置。lib kind
条目由条目类型
常量 IClasspathEntry.CPE_LIBRARY
表示,并具有 IPackageFragmentRoot.K_BINARY
的目录类型
。
清单 1 中的第三个条目具有 kind="var"
和 path="ECLIPSE_HOME/startup.jar"
。在这个条目中,ECLIPSE_HOME
是一个变量。这个由 Eclipse 提供的内置变量将引用 Eclipse 安装目录。用户也可以为工作区定义自定义变量。类路径文件对于项目目录通常都是相对路径或绝对路径。所以,使用变量引用项目目录外部的文件来避免绝对路径是一种很好的做法,因为绝对路径使项目很难实现跨环境共享。请参见 Window > Preferences > Java > Build Path > Classpath Variables 中工作区定义的变量列表。定义了变量后,扩展该变量使其引用变量相关位置的文件,从而实现在构建路径设置中应用变量。
在本例中,通过添加 Eclipse startup.jar 文件对变量进行了扩展。var
条目类似于 lib
条目,惟一不同之处是,在将其应用于类路径之前首先对路径中的第一个元素进行求值运算。var
和 lib
条目之间的另一个区别就是 lib
条目可以引用档案文件或类文件夹,而 var
条目只能引用档案文件。var kind
是二进制类型的条目,由常量 IClasspathEntry.CPE_VARIABLE
表示,并且没有定义目录类型
。所以在引用带有 kind="var"
的 IClasspathEntry 时,绝不应使用 getContentKind()
。然而,需要注意的是,只可以向类路径添加二进制变量扩展,并且为了造成混淆,getContentKind()
总是为变量条目返回 IPackageFragmentRoot.K_SOURCE
。
清单 1 中的第四个条目具有 kind="src"
和 path="/bar"
。该条目引用工作区的另一个项目的源代码(注意:路径从引用工作区根目录的 /
开始)。事实上,这会将 /bar 项目的配置过的输出文件夹添加至编译类路径中,并添加从项目导出的任何类路径条目。虽然 kind
属性与 "src"
相同,但是因为它带有上面的 IClasspathEntry.CPE_SOURCE
,所以该条目由另一个条目类型
常量表示,即 IClasspathEntry.CPE_PROJECT
,并且具有 IPackageFragmentRoot.K_SOURCE
的目录类型
。.classpath 条目的惟一不同之处就是路径属性与工作区相关,而与项目无关。
清单 1 中的第五个条目具有 kind="con"
和 path="org.eclipse.jdt.launching.JRE_CONTAINER"
。本教程主要讨论该类型条目。该条目的类型
常量是 IClasspathEntry.CPE_CONTAINER
,并且没有定义目录类型
。容器条目是对 org.eclipse.jdt.core.IClasspathContainer
实现的逻辑引用。该实现集合一组具体的条目,条目类型为 IClasspathEntry.CPE_LIBRARY
或 IClasspathEntry.CPE_PROJECT
。
下面对类路径条目的类型进行了总结。示例文件取自于 清单 1 中的 .classpath 文件。
要了解对不同类路径条目的详细介绍,请参阅 Javadoc 的 org.eclipse.jdt.core.IClasspathEntry
,要了解如何使用这些不同的类型
通过编程设置构建路径,请参阅 Eclipse 帮助主题 “Setting the Java Build Path”。
在本教程中,术语类路径容器 是指 org.eclipse.jdt.core.IClasspathContainer
的实现。类路径容器是对一组类路径资源的逻辑引用。IClasspathContainer
实现可以对每个项目定义类路径容器条目集。由于条目集是由 IClasspathContainer
定义的,它可以是动态的,也可以是静态的。如果是静态条目集,容器可以返回一组固定的位于熟悉目录的 JAR 集,(例如 JRE System Library)。或者,如果是动态条目集,容器可能会返回一组运行时 JAR,这些 JAR 将根据服务器的部署进行更改。
使用类路径容器的原因有很多,下面列出了一些主要原因:
-
减少混乱
-
您无需将一些单独的 JAR 文件放到一个项目下,而可以将它们分到一个容器中,然后展开该容器来查看单独的 JAR 文件。这样做能够把 Java Package Explore 视图中屏幕的真实状态保存下来。
并且 .classpath 文件所需的条目数量由多个减少至一个。
-
可移植性
- 由于容器条目的路径使用的是逻辑名称,因此没有包含关于文件系统的信息,这使得类路径条目可以移植到不同的机器上,从而能够通过源代码控制管理系统(source control management,SCM)(例如 CVS 或 SVN)轻松实现项目共享。变量条目同样具有这种优势。
-
易于管理
- 如果是针对容器类型而定义类路径容器页面,那么用户可以通过 UI 对容器的属性进行编辑。
-
动态特性
- 动态特性可能是类路径容器最重要的优点,因为任何其他类型的类路径条目都不具备该特性。由于是在需要时才对容器条目进行检索,因此容器条目是动态的。工作区或项目元数据中没有保存有关容器条目的信息。只有当编译和运行这类操作需要使用条目时才会对它们进行检索,因此,这就为基于任何实际因素重定义类路径依赖项提供了一种方法。一般情况下,容器可以将项目目录中所有的 JAR 文件添加到类路径中。事实上,这是 Web App Libraries 类路径容器的一项功能,由 Web Tools Project (WTP) 为 Web 项目的 WEB-INF/lib 文件夹而提供。