На информационном ресурсе применяются рекомендательные технологии (информационные технологии предоставления информации на основе сбора, систематизации и анализа сведений, относящихся к предпочтениям пользователей сети "Интернет", находящихся на территории Российской Федерации)

Подмешайте немного Groovy в приложения Java (исходники). Продолжение

Внедрение Groovy в код Java

Несмотря на то, что решение, работающее в командной строке, лёгкое и удобное, оно не универсально. Если бы мне было интересно перейти на более высокий уровень сложности, я мог бы импортировать мою MP3-утилиту непосредственно в программу Java. В этом случае я смог бы импортировать Song.

class и использовать его так же, как и любой другой класс языка Java. Проблемы с путем классов будут такими же, как и раньше: мне нужно не забыть включить файл архива uber-Groovy , Ant, и файл jid3lib-0.5.jar. В листинге 5 вы можете увидеть, как я импортировал MP3-утилиту Groovy в пример класса Java:

Листинг 5. Встроенный код Groovy

package com.vanward.gembed;

import com.vanward.groovy.Song;
import java.util.Collection;
import java.util.Iterator;

public class SongEmbedGroovy{

public static void main(String args[]) {
Collection coll = (Collection)Song.getSongsForDirectory
("C:\\music\\temp\\mp3s");
for(Iterator it = coll.iterator(); it.hasNext();){
System.out.println(it.next());
}
}
}

Загрузчики классов Groovy

Вы думаете, что уже всё узнали? Оказывается, есть ещё несколько способов позабавиться с Groovy в Java. Помимо встраивания сценариев Groovy в программы Java с помощью прямой компиляции у меня также есть несколько вариантов встраивания непосредственно сценариев.

Например, я могу с помощью GroovyClassLoader Groovy осуществить динамическую загрузку сценария Groovy и его исполнения, как показано в листинге 6:

Листинг 6. GroovyClassLoader динамически загружает и исполняет сценарий Groovy

package com.vanward.gembed;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.MetaMethod;
import java.io.File;

public class CLEmbedGroovy{

public static void main(String args[]) throws Throwable{

ClassLoader parent = CLEmbedGroovy.class.getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);

Class groovyClass = loader.parseClass(
new File("C:\\dev\\groovy-embed\\src\\groovy\ com\\vanward\\groovy\\Songs.
groovy"));

GroovyObject groovyObject = (GroovyObject)
groovyClass.newInstance();

Object[] path = {"C:\\music\\temp\\mp3s"};
groovyObject.setProperty("args", path);
Object[] argz = {};

groovyObject.invokeMethod("run", argz);

}
}

 
Классы Meta

Если вы один из тех психов, кому нравятся отражения и те замечательные вещи, которые можно с ними сделать, классы Meta Groovy сведут вас с ума. Точно так же, как и в случае отражений, используя эти классы, вы можете узнать много нового о GroovyObject, например, о его методах, и вы можете действительно создавать новые алгоритмы и выполнять их. Это, к слову, и есть сердце Groovy -- и только представьте, как оно работает, когда вы запускаете сценарии!

Обратите внимание, что по умолчанию загрузчик класса загружает класс, соответствующий названию сценария -- в данном случае, Songs.class, а не Song.class>. Поскольку мы с вами знаем, что Songs.class расширяет класс Script Groovy, понятно, что моим следующим действием будет выполнение метода run().

Вы, наверное, помните, что мой сценарий Groovy также зависел от аргументов, передаваемых во время работы программы. Поэтому мне нужно настроить переменную args соответствующим образом, так как в данном случае я первым элементом установил название директории.

Больше динамики

Альтернатива использованию компилированных классов и динамической загрузке GroovyObject посредством загрузчиков классов состоит в использовании GroovyScriptEngine и GroovyShell для динамического выполнения сценариев Groovy.

Внедрение объекта GroovyShell в обычные классы Java позволяет вам динамически выполнять сценарии Groovy так же, как это делает загрузчик класса. Кроме того, это даёт вам несколько возможностей запуска сценариев. В листинге 7 показано, как GroovyShell внедрен в обычный класс Java:

Листинг 7. Внедрение GroovyShell

package com.vanward.gembed;

import java.io.File;
import groovy.lang.GroovyShell;

public class ShellRunEmbedGroovy{

public static void main(String args[]) throws Throwable{

String[] path = {"C:\\music\\temp\\mp3s"};
GroovyShell shell = new GroovyShell();
shell.run(new File("C:\\dev\\groovy-embed\\src\\groovy\ com\\vanward\\groovy\\Songs.groovy"),
path);
}
}

Как вы можете увидеть, сценарий Groovy запускается очень просто. Я просто создаю экземпляр GroovyShell, передаю название сценария и вызываю метод run() .

Но это не всё. Если хотите, вы можете запросить экземпляр GroovyShell для типа Script вашего сценария. Используя тип Script, вы можете передавать объект Binding, содержащий все нужные параметры, и вызывать метод run(), как показано в листинге 8.

Листинг 8. Забавляемся с GroovyShell

package com.vanward.gembed;

import java.io.File;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;

public class ShellParseEmbedGroovy{

public static void main(String args[]) throws Throwable{
GroovyShell shell = new GroovyShell();
Script scrpt = shell.parse(
new File("C:\\dev\\groovy-embed\\src\\groovy\ com\\vanward\\groovy\\Songs.groovy"));

Binding binding = new Binding();
Object[] path = {"C:\\music\\temp\\mp3s"};
binding.setVariable("args",path);
scrpt.setBinding(binding);

scrpt.run();
}
}

Механизм сценариев Groovy

Объект GroovyScriptEngine работает так же, как GroovyShell для динамически запускаемых сценариев. Отличие GroovyScriptEngine состоит в том, что при создании экземпляра вы можете указать ему несколько директорий, после чего вы в любое время можете вызвать несколько сценариев, как показано в листинге 9:

Листинг 9. GroovyScriptEngine в действии

package com.vanward.gembed;

import java.io.File;
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

public class ScriptEngineEmbedGroovy{

public static void main(String args[]) throws Throwable{

String[] paths = {"C:\\dev\\groovy-embed\\src\\groovy\ com\\vanward\\groovy"};
GroovyScriptEngine gse = new GroovyScriptEngine(paths);
Binding binding = new Binding();
Object[] path = {"C:\\music\\temp\\mp3s"};
binding.setVariable("args",path);

gse.run("Songs.groovy", binding);
gse.run("BusinessObjects.groovy", binding);
}
}

В листинге 9 я передаю массив, содержащий нужный мне путь, созданному экземпляру GroovyScriptEngine, создаю старый знакомый объект Binding и выполняю также знакомый сценарий Songs.groovy . Просто ради забавы, я запускаю сценарий BusinessObjects.groovy, который вы, возможно, помните из начала этого обсуждения.

Среда сценариев Bean

Последним, но весьма важным, способом является среда сценариев Bean Scripting Framework (BSF) проекта Jakarta. Цель BSF - предложить общий API для внедрения любого языка сценариев, в том числе и Groovy, в обычное приложение Java. Этот стандартный, хотя, возможно, чрезмерно общий, подход позволяет вам внедрять сценарии Groovy без всяких усилий.

Помните приведенный выше сценарий BusinessObjects? В листинге 10 показано, как просто BSF позволяет вам встроить его в обычную программу Java:

Листинг 10. BSF в работе

package com.vanward.gembed;

import org.apache.bsf.BSFManager;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.io.File;
import groovy.lang.Binding;

public class BSFEmbedGroovy{

public static void main(String args[]) throws Exception {
String fileName = "C:\\dev\\project\\src\\groovy\ com\\vanward\\groovy\\BusinessObjects.groovy";
//this is required for bsf-2.3.0
//the "groovy" and "gy" are extensions
BSFManager.registerScriptingEngine("groovy",
"org.codehaus.groovy.bsf.GroovyEngine", new
String[] { "groovy" });
BSFManager manager = new BSFManager();
//DefaultGroovyMethods.getText just returns a
//string representation of the contents of the file
manager.exec("groovy", fileName, 0, 0,
DefaultGroovyMethods.getText(new File(fileName)));
}
}

Заключение

Если что и ясно из этой статьи, так это то, что Groovy открывает множество вариантов повторного использования в коде Java. Во всех случаях, от компиляции сценариев Groovy в обычные старые файлы .class Java до динамической загрузки и запуска сценариев, главное, на что нужно обращать внимание - это гибкость и возможность совместной работы. Компиляция сценариев Groovy в обычные файлы .class - это простейший способ использования функций, которые вы встраиваете, тогда как динамическая загрузка сценариев упрощает добавление и изменение алгоритмов работы без затрат времени на компиляцию. (Конечно же, этот вариант работает только в том случае, если интерфейс не изменился.)

Встраивание языков сценариев в обычный код Java не является повседневным явлением, но иногда такие возможности представляются. В приведенных здесь примерах я встраивал простую утилиту поиска по каталогам в приложение Java, которое может быть MP3-плеером или другой утилитой для работы с MP3. Несмотря на то, что я могу переписать мою утилиту поиска файлов MP3 в код Java, мне не нужно этого делать: Groovy великолепно совместим с языком Java, и, кроме того, я отлично позабавился, разбираясь со всеми возможностями!

Рекомендуем
Популярное
наверх