2

假设我编写了一个名为的模块/库mylib,它使用了一个名为 的内部/隐藏的第三方模块/库internalmylib的 API不公开该第三方库的任何功能,并且在不久的将来它可能会被其他东西取代。

module mylib {
    requires internal;
    exports some.pgk.from.mylib;
}

但这是我的问题。内部库需要对通过mylib的公共 API 传递的类/对象进行反射访问才能完成工作。

使用我的库命名的示例应用程序/模块app必须定义以下 moduleinfo.java

module app {
    requires mylib;
    opens some.pkg.from.app to internal;
}

但这很糟糕,因为它会将内部使用的模块暴露给我的库的用户,并且我将来无法在不破坏app的情况下删除/更改它。理想情况下,我希望允许模块内部反射访问对mylib开放的所有模块:

module app {
    requires mylib;
    opens some.pkg.from.app to mylib; // also open to internal without naming it
}

这可以用当前的(Java 17)模块系统来完成吗?如果这是不可能的,是否有一个好的解决方法?

4

1 回答 1

4

我看到了四种可能的解决方案:

  1. appModule.addOpens("some.pkg.from.app", internalModule)从调用mylib

    如果此模块至少打开了调用者模块的包,则更新此模块以打开给定模块的包。

    这是有效的,因为myapp已经打开了模块的包some.pkg.from.app-mylib这是调用者模块。
    您必须为已打开到您的模块的每个包重复此操作。
    如果你不处理模块层,你可以反射性地枚举所有对你的模块开放的包。
    如果您必须处理图层 - 您必须枚举所有图层 - 并且可以在运行时添加这些图层。

  2. 传递一个Consumer<AccessibleObject> makeAccessible = ao -> ao.setAccessible(true);internal

    这是有效的,因为 now 的调用者setAccessible是 now mylib
    (或者myapp,如果消费者来自那里。)

  3. 将完整权限查找mylib传递到internal

    您可以使用此Lookup来调用AccessibleObject.setAccessible.
    或者也许做其他事情,比如打电话Module.addOpens

  4. 将完整权限查找从myappto传递给mylib,而后者又将其传递给internal

    这里的好处是您不需要声明您打开了一个包 - 因为MethodHandle您通过传递的查找进行的任何查找都将像从 调用它一样工作myapp
    您甚至可以限制此查找。

于 2021-10-27T11:14:34.647 回答