假设我写了一个名为mylib
的模块/库,它使用了一个名为internal
的内部/隐藏的第三方模块/库。mylib的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)模块系统中完成吗?如果这是不可能的,有没有一个好的解决方案?
我看到了四种可能的解决方案:
-
从
mylib
呼叫appModule.addOpens("some.pkg.from.app", internalModule)
。如果此模块至少向调用方模块打开了一个包,则更新此模块以向给定模块打开包。
这可以工作,因为
myapp
已经打开了some.pkg.from.app
包到mylib
模块-这是调用方模块。
你必须对每个打开到你模块的包重复这个操作。
如果你不处理模块层,你可以反射地枚举所有对你的模块开放的包。
如果你必须处理层-你必须枚举所有的层-这些可以在运行时添加。 -
将
Consumer<AccessibleObject> makeAccessible = ao -> ao.setAccessible(true);
传递给internal
。
(如果消费者来自myapp
,则为CC_13) -
传递
mylib
到internal
的全权限查找。你可以使用这个查找来调用
AccessibleObject.setAccessible
.
或者做其他事情,比如调用Module.addOpens
. -
将
myapp
的完整权限查找传递给mylib
, CC_19再将其传递给internal
。
这样做的好处是你不需要声明你打开了一个包——因为你通过传递的查找来查找的任何MethodHandle
都会像从myapp
调用一样工作。
你甚至可以限制这种查找。