我定制了Groovy类加载器,用于从文件系统中的目录加载类。
现在我有了groovy类,例如,
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;
}
}现在,当我们在目录中解析那些groovy文件时。然后我们找到一个无限循环日志,如下所示,
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中解决这个问题呢?
请帮帮我!非常感谢!
发布于 2015-09-24 18:24:15
对于编译器为避免这个问题所做的内部查找,标志lookupScriptFiles是假的。与其覆盖loadClass,不如通过set/getResourceLoader使用GroovyResourceLoader或在GroovyClassLoader上覆盖getResource(String) (这个方法是从资源加载器调用的)。这样,编译器就能够自动查找源代码并将其添加到编译队列中。
https://stackoverflow.com/questions/32765857
复制相似问题