在Java 9中加载类和资源

kaq*_*qao 39 java java-platform-module-system spring-boot java-9

我正在阅读InfoQ上引用Reinhold的这篇文章:

开发人员仍然可以使用Java 9中的Java类路径为Java运行时搜索类和资源文件.只是使用Java 9的模块,开发人员不再需要类路径.

所以现在我的问题是:执行上面列出的任务的Java 9方法是什么?如何动态加载例如图像(缺少相对路径的摆弄)?

更有趣的是,如何检查一个类是否可用并动态做出决定(例如,检查Jackson是否可用,如果是,请将其用于JSON序列化,如果不使用别的东西)?

文章还提到Spring Boot已经支持Java 9,Spring Boot肯定会做很多动态加载.那么也许有人知道Spring可以看到的代码片段?

Mar*_*old 86

首先,为了记录,我既没有说也没有写上面引用的文字.我从来没有这么说过.这只是有关出版物的草率报道.

了解Java 9中的类加载和资源查找最重要的是,从根本上说,它们没有改变.无论代码是从类路径还是模块路径加载,您都可以通过调用Class::forName和类中的各种getResource*方法,以Class与以往相同的方式搜索类和资源ClassLoader.仍然有三个内置类加载器,就像在JDK 1.2中一样,它们具有相同的委托关系.因此,许多现有代码都可以使用,开箱即用.

有一些细微差别,如JEP 261所述:内置类加载器的具体类型已经改变,以前由引导类加载器加载的一些类现在由平台类加载器加载,以提高安全性.假定内置类加载器是一个URLClassLoader或由引导类加载器加载类的现有代码可能因此需要进行微小的调整.

最后一个重要的区别是模块中的非类文件资源默认是封装的,因此除非它们的有效包,否则不能从模块外部定位 open.从您自己的模块加载资源,最好使用资源的查找方法,Class或者Module,它可以找到任何资源的模块中,而不是那些ClassLoader,只能在找到非类文件的资源open模块的封装.


Mic*_*ter 5

[编辑:这个答案是在马克的权威答案之前写的。我已经修改了我的以提供一个简单的例子,可在 GitHub 上找到。]

根据此视频,Java 9 中的类加载保持不变。

例如,假设我们有:

  • 一个example.jar包含在包中的图像net.codetojoy.example.resources
  • 加强罐子,net.codetojoy.example.Composer是公共的(和出口,在适用的情况下)
  • 一个简单的App类,example.jar用作库并尝试从中加载图像

中的相关代码App

static InputStream getResourceAsStream(String resource) 
    throws Exception {

    // Load net/codetojoy/example/resource/image.jpg
    // Assume net.codetojoy.example.Composer is public/exported
    // resource is 'resource/image.jpg'

    InputStream result = Composer.class.getResourceAsStream(resource);

    return result;
}   
Run Code Online (Sandbox Code Playgroud)

以下是example.jarJDK 9中的一些情况:

老式的非模块化 Jar

如果example.jar不是模块,则代码正常工作。类加载不变。

带开放式包装的模块化罐

在这种情况下,这是module-info.java文件:

module net.codetojoy.example {
    // export the Composer class
    exports net.codetojoy.example;

    // image is available
    opens net.codetojoy.example.resources;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,图像可以由客户端加载,因为包是打开的。

不带开包的模块化罐

在这种情况下,module-info.java是:

module net.codetojoy.example {
    // export the Composer class
    exports net.codetojoy.example;

    // package not opened: image not available
    // opens net.codetojoy.example.resources;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,图像无法加载,因为强封装:模块通过不打开包装来保护图像。

GitHub 上的完整源代码。