Picocli 必须自省命令树。这样做需要为每个命令加载域对象类,这会减慢 jvm 启动速度。
有哪些选择可以避免这种启动滞后?我提出的一种解决方案在https://github.com/remkop/picocli/issues/482中进行了描述:
我正在使用反射将任何类加载推迟到选择命令之后。这样,只有命令类本身被加载,最后是实现用户请求的单个命令的类:
abstract class BaseCommand implements Runnable {
interface CommandExecutor {
Object doExecute() throws Exception;
}
// find the CommandExecutor declared at the BaseCommand subclass.
protected Object executeReflectively() throws Exception {
Class<?> innerClass = getExecutorInnerClass();
Constructor<?> ctor = innerClass.getDeclaredConstructor(getClass());
CommandExecutor exec = (CommandExecutor) ctor.newInstance(this);
return exec.doExecute();
}
private Class<?> getExecutorInnerClass() throws ClassNotFoundException {
return getClass().getClassLoader().loadClass(getClass().getName() + "$Executor");
}
public void run() {
try {
executeReflectively();
} catch(...){
/// usual stuff
}
}
}
一个具体的表扬类:
@Command(...)
final class CopyProfile extends BaseCommand {
@Option String source;
@Option String dest;
// class must NOT be static and must be called "Executor"
public class Executor implements CommandExecutor {
@Override
public Object doExecute() throws Exception {
// you can basically wrap your original run() with this boilerplate
// all the CopyProfile's field are in scope!
FileUtils.copy(source, dest);
}
}
}
似乎https://github.com/remkop/picocli/issues/500可能会为此提供最终解决方案。在那之前还有什么其他选择?