是的,只要您正确实施ForwardingJavaFileManager,这是完全可能的。两个最重要的方法是inferBinaryName() 和list()。如果您正确设置这两个,编译器将能够解析您之前编译的类。
inferBinaryName() 必须返回类'simple name(例如,com.test.Test 的推断二进制名称将只是 Test)。这是我的实现(我的JavaFileObject 子类称为InAppJavaFileObject):
@Override
public String inferBinaryName(Location location, JavaFileObject javaFileObject) {
if(location == StandardLocation.CLASS_PATH && javaFileObject instanceof InAppJavaFileObject) {
return StringUtils.substringBeforeLast(javaFileObject.getName(), ".java");
}
return super.inferBinaryName(location, javaFileObject);
}
请注意,我从最后剥离了“.java”。构造JavaFileObject时,文件名必须以“.java”结尾,但如果后面不去掉后缀,编译器就找不到你的类了。
list() 有点复杂,因为您必须小心地与您的委托文件管理器配合使用。在我的实现中,我将完全限定的类名映射到我的 JavaFileObject 的子类,我可以对其进行迭代:
@Override
public Iterable<JavaFileObject> list(Location action, String pkg, Set<JavaFileObject.Kind> kind, boolean recurse) throws IOException {
Iterable<JavaFileObject> superFiles = super.list(action, pkg, kind, recurse);
// see if there's anything in our cache that matches the criteria.
if(action == StandardLocation.CLASS_PATH && (kind.contains(JavaFileObject.Kind.CLASS) || kind.contains(JavaFileObject.Kind.SOURCE))) {
List<JavaFileObject> ourFiles = new ArrayList<JavaFileObject>();
for(Map.Entry<String,InAppJavaFileObject> entry : files.entrySet()) {
String className = entry.getKey();
if(className.startsWith(pkg) && ("".equals(pkg) || pkg.equals(className.substring(0, className.lastIndexOf('.'))))) {
ourFiles.add(entry.getValue());
}
}
if(ourFiles.size() > 0) {
for(JavaFileObject javaFileObject : superFiles) {
ourFiles.add(javaFileObject);
}
return ourFiles;
}
}
// nothing found in our hash map that matches the criteria... return
// whatever super came up with.
return superFiles;
}
一旦您正确实施了这些方法,其余的就可以工作了。享受吧!