我定制了 Groovy 类加载器,用于从文件系统中的目录加载类。
现在我有下面的常规类(class),
ICommentService.groovy
public interface ICommentService {
public void a();
}
CommentService.groovy
public class CommentService implements ICommentService {
public void a() {
//doing something...
}
}
IMomentService.groovy
public interface IMomentService {
public void b();
}
MomentService.groovy
import ICommentService;
import CommentService;
public class MomentService implements IMomentService {
public void b() {
ICommentService commentService = new CommentService();
commentService.a();
//doing something
}
}
我的自定义类加载器代码如下,
public class MyGroovyClassLoader extends GroovyClassLoader {
private long version;
private HashMap<String, ClassHolder> classCache;
private HashSet<String> pendingGroovyClasses;
public MyGroovyClassLoader(ClassLoader parentClassLoader,
CompilerConfiguration cc) {
super(parentClassLoader, cc);
classCache = new HashMap<>();
}
public Class<?> parseGroovyClass(String key, File classFile)
throws CoreException {
ClassHolder holder = classCache.get(key);
if(holder != null && holder.getParsedClass() != null) {
LoggerEx.info(TAG, "Load groovy class " + key
+ " from cache");
return holder.getParsedClass();
}
try {
Class<?> parsedClass = parseClass(classFile);
if (parsedClass != null) {
holder = new ClassHolder();
holder.parsedClass = parsedClass;
classCache.put(key, holder);
}
LoggerEx.info(TAG, "Parse groovy class " + key
+ " successfully");
return parsedClass;
} catch (Throwable e) {
e.printStackTrace();
throw new CoreException(
ChatErrorCodes.ERROR_GROOVY_PARSECLASS_FAILED,
"Parse class " + classFile + " failed, "
+ e.getMessage());
}
}
@Override
public Class loadClass(String name, boolean lookupScriptFiles,
boolean preferClassOverScript) throws ClassNotFoundException,
CompilationFailedException {
// TODO Auto-generated method stub
Class<?> loadedClass = null;
if(pendingGroovyClasses.contains(name)) {
String key = name.replace(".", "/") + ".groovy";
try {
loadedClass = parseGroovyClass(key, new File(path + key));
if(loadedClass != null)
return loadedClass;
} catch (CoreException e) {
e.printStackTrace();
LoggerEx.error(TAG, "parse groovy class failed while load class, " + e.getMessage());
}
}
try {
loadedClass = super.loadClass(name, lookupScriptFiles,
preferClassOverScript);
} catch (ClassNotFoundException e) {
}
return loadedClass;
}
public ClassHolder getClass(String classPath) {
return classCache.get(classPath);
}
public long getVersion() {
return version;
}
public String toString() {
return MyGroovyClassLoader.class.getSimpleName() + "#" + version;
}
}
现在,当我们解析目录中的那些常规文件时。 然后我们发现了一个无限循环日志如下,
Parse groovy class ICommentService.groovy successfully
Parse groovy class IMomentService.groovy successfully
Load groovy class ICommentService.groovy from cache
Load groovy class IMomentService.groovy from cache
Load groovy class ICommentService.groovy from cache
Load groovy class IMomentService.groovy from cache
Load groovy class ICommentService.groovy from cache
Load groovy class IMomentService.groovy from cache
Load groovy class ICommentService.groovy from cache
Load groovy class IMomentService.groovy from cache
Load groovy class ICommentService.groovy from cache
Load groovy class IMomentService.groovy from cache
Load groovy class ICommentService.groovy from cache
Load groovy class IMomentService.groovy from cache
问题是两个类相互导入,可以理解为什么会发生循环。但java类加载器似乎可以很好地处理这个问题。那么在 Groovy 中我们如何解决这个问题呢?
请帮忙!非常感谢!
最佳答案
对于编译器执行的内部查找,标志lookupScriptFiles 为 false,以避免出现此问题。您应该通过 set/getResourceLoader 使用 GroovyResourceLoader
或覆盖 GroovyClassLoader 上的 getResource(String)
(此方法是从资源中调用的),而不是覆盖 loadClass
装载机)。这样编译器将能够自行查找源代码并将其自动添加到编译队列中。
关于java - 自定义类加载器时,两个groovy类相互导入导致循环编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32765857/