GroovyClassLoader — добавление проанализированных классов в путь к классам

У меня есть библиотека, которая позволяет клиентам предоставлять список текстовых файлов, каждый из которых содержит код groovy для класса, расширяющего класс java Z. Например, файл «A.groovy» содержит

package com.mypkg;

public class A extends Z {

    @Override
    public void someMethod() {

        // do something A-ish

    }
}

и т.п.

Библиотека компилирует каждый из них и (в этом случае) возвращает клиентам экземпляр типа Z.

Моя проблема возникает, когда клиенту нужно что-то вроде этого:

package com.mypkg;

public class B extends A {        // extends A!

    @Override
    public void someMethod() {

        // do something B-ish instead of A-ish

    }
}

где B расширяет A, а класс A был проанализирован до класса B.

Проблема в том, что GroovyClassLoader не может найти класс A, хотя он только что проанализировал A. Вот код, который компилирует скрипты и создает экземпляры:

    for (String fileName : listOfScriptFiles) {

        InputStream in = getInputStreamFromFile(fileName);

        CompilerConfiguration compConfig = new CompilerConfiguration();
        GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread()
            .getContextClassLoader(), compConfig);

        Z service = null;

        Class clazz = classLoader.parseClass(in);
        service = (Z) clazz.newInstance();

        return service;
    }

Есть ли способ «зарегистрировать» класс A в среде выполнения, чтобы при попытке Groovy скомпилировать класс B он не жаловался, что класса A не существует?

ОБНОВЛЕНИЕ

На самом деле я смог решить эту проблему, создав экземпляр GroovyClassLoader вне цикла, который выполняет итерацию по списку кодов клиента, поэтому загрузчик классов, который анализирует A, тот же, что и B.

Тем не менее, вопрос остается в силе, потому что я мог представить себе случай, когда в одной части чьего-то кода они анализируют A, а затем в совершенно другой части, где тот же самый загрузчик классов недоступен, они анализируют B.


person Roy Truelove    schedule 30.04.2012    source источник
comment
Можете ли вы добавить немного больше деталей к вашему вопросу? Например, вы не показываете, как вы определили переменную в.   -  person djangofan    schedule 30.04.2012
comment
«in» — это просто исходный код из списка. Уточнено с некоторым контекстом.   -  person Roy Truelove    schedule 30.04.2012
comment
Вы можете добавить свою команду, которая запускает сценарий Groovy?   -  person djangofan    schedule 01.05.2012
comment
Скрипты никогда не "запускаются". Они создают экземпляры подклассов класса Z, которые затем используются в java.   -  person Roy Truelove    schedule 01.05.2012


Ответы (1)


По моему опыту работы с загрузчиком классов Groovy (который в этом отношении похож на загрузчик классов Ant и beanshell), вы должны заранее решить, собираетесь ли вы использовать системный загрузчик классов по умолчанию, и в этом случае вы должны создать путь к классам в команда, которая запускает сценарий Groovy, ИЛИ, с другой стороны, вы указываете ТОЛЬКО банку groovy в пути к классам командной строки, а затем динамически добавляете классы в начале своего сценария Groovy в пользовательском загрузчике классов.

Вы не предоставляете много информации в своем вопросе, но я предполагаю, что вы поместили класс «A» в путь к классам до того, как запустили скрипт, а затем попытались динамически загрузить класс «B». Насколько я знаю, это не сработает.

ПРИМЕЧАНИЕ. Я сам пытался понять, как это сделать. Кажется, что это возможно, но я до сих пор не понял.

person djangofan    schedule 30.04.2012