如何在java中动态加载类、资源、jar?

How to load classes, resources, jars dynamically in java?

这里我们展示了两个项目结构。

  1. 第一个用于 多个项目
  2. 还有一个用于单个项目结构。

我们想要assemble由多个项目组成的单个项目。我们的要求是加载它的依赖项,例如来自不同的 classesresourcesjars java 程序动态定位。不添加 class 路径条目到它的 jar MANIFEST.MF.

您可以在 运行 时添加 java 选项以识别 class 路径,但我们更喜欢通过 java 程序动态加载。

/opt/java/chorke/multiple/projects/home/
    ├─ bin/
    │   ├─ mspn/
    │   │   ├─ lib/
    │   │   │   ├─ chorke-mspn-utlity-2.0.00-SNAPSHOT.jar
    │   │   │   └─ chorke-mspn-webapp-2.0.00-SNAPSHOT.jar
    │   │   ├─ chorke-mspn-server-2.0.00-SNAPSHOT.jar         [executable jar]
    │   │   ├─ README.md
    │   │   └─ LICENSE
    │   ├─ mllp/
    │   │   ├─ lib/
    │   │   │   ├─ chorke-mllp-utlity-2.0.00-SNAPSHOT.jar
    │   │   │   └─ chorke-mllp-webapp-2.0.00-SNAPSHOT.jar
    │   │   ├─ chorke-mllp-server-2.0.00-SNAPSHOT.jar         [executable jar]
    │   │   ├─ README.md
    │   │   └─ LICENSE
    │   └─ itis/
    │       ├─ lib/
    │       │   ├─ chorke-itis-utlity-2.0.00-SNAPSHOT.jar
    │       │   └─ chorke-itis-webapp-2.0.00-SNAPSHOT.jar
    │       ├─ chorke-itis-server-2.0.00-SNAPSHOT.jar         [executable jar]
    │       ├─ README.md
    │       └─ LICENSE
    ├─ lib/
    │   ├─ commons-lang3-3.3.2.jar
    │   ├─ ...more...hidden...jars...here.jar
    │   ├─ slf4j-log4j12-1.7.12.jar
    ├─ opt/
    │   ├─ org.eclipse.swt.gtk.linux.x86-4.4.2.jar
    │   ├─ org.eclipse.swt.cocoa.macosx.x86-4.4.2.jar
    │   ├─ ...more...optional...hidden...jars...here.jar
    │   └─ org.eclipse.swt.win32.win32.x86_64-4.4.2.jar
    └─ etc/
        ├─ mspn/
        │   ├─ application.properties
        │   ├─ application.yml
        │   └─ log4j.xml
        ├─ mllp/
        │   ├─ application.properties
        │   ├─ application.yml
        │   └─ log4j.xml
        └─ itis/
            ├─ application.properties
            ├─ application.yml
            └─ log4j.xml

在这里我们将多项目结构拆分为单个项目,以供您考虑。

/opt/java/chorke/single/project/home/
    ├─ bin/
    │   └─ itis/
    │       ├─ lib/
    │       │   ├─ chorke-itis-utlity-2.0.00-SNAPSHOT.jar
    │       │   └─ chorke-itis-webapp-2.0.00-SNAPSHOT.jar
    │       ├─ chorke-itis-server-2.0.00-SNAPSHOT.jar         [executable jar]
    │       ├─ README.md
    │       └─ LICENSE
    ├─ lib/
    │   ├─ commons-lang3-3.3.2.jar
    │   ├─ ...more...hidden...jars...here.jar
    │   ├─ slf4j-log4j12-1.7.12.jar
    ├─ opt/
    │   ├─ org.eclipse.swt.gtk.linux.x86-4.4.2.jar
    │   ├─ org.eclipse.swt.cocoa.macosx.x86-4.4.2.jar
    │   ├─ ...more...optional...hidden...jars...here.jar
    │   └─ org.eclipse.swt.win32.win32.x86_64-4.4.2.jar
    └─ etc/
        └─ itis/
            ├─ application.properties
            ├─ application.yml
            └─ log4j.xml

已编辑

假设我们想 运行 chorke-itis-server-2.0.00-SNAPSHOT.jar

java -jar ./bin/itis/chorke-itis-server-2.0.00-SNAPSHOT.jar

命令,但它不会执行,因为它在 class 路径中缺少依赖性,例如:-

  1. 自己的jar库./bin/itis/lib/*.jar
  2. 常用jar库./lib/*.jar
  3. 可选jar库./opt/*.jar
  4. 配置资源./etc/itis/*.*

这些依赖项不会像往常一样加载。我们应该做更多的工作来识别这些 class 路径。它将通过提供 class 路径参数或由 java 程序动态地从命令行传递。

您能否通过核心 java 或任何类型的开源框架帮助我们构建动态 class 加载程序?

这是您需要的单个示例项目结构,而 BootstrapMainApplicationcom.chorke.boot 包中用于执行 java 应用程序的主要 class :-

/opt/java/chorke/itis/project/home/
    ├─ bin/
    │   └─ itis/
    │       ├─ lib/
    │       │   ├─ chorke-itis-utlity-2.0.00-SNAPSHOT.jar
    │       │   └─ chorke-itis-webapp-2.0.00-SNAPSHOT.jar
    │       ├─ chorke-itis-server-2.0.00-SNAPSHOT.jar         [executable jar]
    │       ├─ classes/
    │       ├─ README.md
    │       └─ LICENSE
    ├─ lib/
    │   ├─ usr/
    │   │   ├─ chorke-amqp-client-2.0.00-SNAPSHOT.jar
    │   │   └─ chorke-comn-spring-2.0.00-SNAPSHOT.jar
    │   └─ gpl/
    │       ├─ activemq-broker-5.10.2
    │       ├─ commons-lang3-3.3.2.jar
    │       ├─ ..more...and..more..jar
    │       └─ slf4j-log4j12-1.7.12.jar
    ├─ etc/
    │   └─ itis/
    │       ├─ application.properties
    │       ├─ application.yml
    │       └─ log4j.xml
    ├─ launch.bat
    └─ launch.sh

考虑到这个项目结构你可以写bat或者shell脚本命名为launch.batlaunch.sh 用于 Windows 以及 Linux 平台。

launch.bat

goto launch

:launch
    SET CKI_HOME=.
    SET BIN_PATH=%CKI_HOME%\bin
    SET LIB_PATH=%CKI_HOME%\lib
    SET ETC_PATH=%CKI_HOME%\etc
    SET ITI_HOME=%BIN_PATH%\itis
    SET CLS_PATH=%ETC_PATH%\itis\;%ITI_HOME%\classes\
    SET CLS_PATH=%CLS_PATH%;%LIB_PATH%\gpl\*;%LIB_PATH%\usr\*;%ITI_HOME%\lib\*;%ITI_HOME%\*

    @REM SET CMD_EXCE=java -cp %CLS_PATH% com.chorke.boot.BootstrapMainApplication
    SET CMD_EXCE=java -classpath %CLS_PATH% com.chorke.boot.BootstrapMainApplication
    %CMD_EXCE%

对于 Linux 平台,使用此 shell 脚本可能工作正常

launch.sh

#!/bin/bash

function launch(){
    CKI_HOME='.';
    BIN_PATH="$CKI_HOME/bin";
    LIB_PATH="$CKI_HOME/lib";
    ETC_PATH="$CKI_HOME/etc";
    ITI_HOME="$BIN_PATH/itis";
    CLS_PATH="$ETC_PATH/itis/:$ITI_HOME/classes/";
    CLS_PATH="$CLS_PATH:$LIB_PATH/gpl/*:$LIB_PATH/usr/*:$ITI_HOME/lib/*:$ITI_HOME/*";

    #CMD_EXCE="java -cp $CLS_PATH com.chorke.boot.BootstrapMainApplication";
    CMD_EXCE="java -classpath $CLS_PATH com.chorke.boot.BootstrapMainApplication";
    $CMD_EXCE;
}

launch;

我认为这些脚本将有助于构建您自己的应用程序 ecosystem/structure 以及能够从不同位置加载 classes/config/library。