java - 自定义类加载器时,两个groovy类相互导入导致循环编译错误

标签 java class groovy classloader

我定制了 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/

相关文章:

java - 报错找不到主类程序netbeans后会退出

java - 使用 java HSSF POI 填充 excel 中的字段 - excel 无法正确排序日期字段

java - 哪些类对于运行 Java VM 是绝对必要的?

spring-websocket 将命令结果流式传输回浏览器

java - hibernate ehcache测试失败

java - 即使已读取一行,BufferedReader#readLine() 也会挂起

java - 用户输入验证java类

C++ 嵌套类方法

testing - gradle 测试阶段?

groovy - Groovy 脚本中的全局方法