【发布时间】:2015-09-24 15:57:04
【问题描述】:
我定制了 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 中解决这个问题呢?
请帮忙!非常感谢!
【问题讨论】:
标签: java class groovy classloader