|
Навигация
|
Главная » Java Практически Groovy: Подмешайте немного Groovy в приложения Java (исходники)Источник: IBM developerWorks Россия Эндрю Гловер Если вы уже читали статьи из этой серии, вы могли увидеть, что существует множество интересных способов использования Groovy, и одним из основных преимуществ Groovy является продуктивность работы программиста. Код Groovy чаще всего более прост и лёгок в написании, чем код Java, что делает его ещё более ценным дополнением к вашему инструментарию разработки. С другой стороны, как я уже неоднократно отмечал в рамках серии, Groovy не является заменой языка Java и не предназначен для этого. Итак, вопрос состоит в том, можете ли вы внедрить Groovy в практику программирования Java, и полезно ли это, а если полезно - то когда ?В этом месяце я попытаюсь ответить на этот вопрос. Я начну с того, что вы уже знаете -- как сценарии Groovy компилируются в Java-совместимые файлы класса, после чего углублюсь в подробное описание того, как средства компиляции Groovy ( groovyc ) делают это возможным. Понимание того, как работает Groovy -- это первый шаг к использованию его в коде JavaОбратите внимание, что некоторые методики программирования, продемонстрированные в этой статье, лежат в основе инфраструктур Groovlets и GroovyTestCase Groovy, которые я рассматривал в прошлом месяце.Правда ли, что браки заключаются на небесах?В одной из предыдущих статей этой серии, когда я показывал, как проводить модульное тестирование обычных программ Java с помощью Groovy, вы могли заметить одну особенность: я компилировал сценарии Groovy. Действительно, я скомпилировал модульные тесты в обычные файлы .class Java и запустил их в процессе компоновки Maven.Компиляция такого типа выполняется путем вызова команды groovyc , которая компилирует сценарии Groovy в старые добрые файлы .class, совместимые с Java. Например, если в сценарии объявляется три класса, вызов groovyc приведёт к созданию трёх файлов .class. Сами файлы будут соответствовать стандартным правилам Java, согласно которым название файла .class совпадает с названием класса.Для примера давайте посмотрим на листинг 1, который создаёт простой сценарий, объявляющий несколько классов. Вы можете увидеть, что выводит команда groovyc :Листинг 1. Декларация и компиляция класса в Groovy
В листинге 1 я объявил три класса -- Person , Address и ContactNumber . Приведенный ниже код создаёт объекты только что определенных типов и вызывает метод toString() . Пока всё довольно просто, но давайте посмотрим, что получилось в результате работы groovyc , приведенном в листинге 2:Листинг 2. Классы, созданные командой groovyc
Ого, пять файлов .class! Существование файлов Person , Address и ContactNumber понятно, но зачем нужно ещё два?Выясняется, что Person$_toString_closure1.class появился в результате наличия замыкания в методе toString() класса Person . Фактически он является внутренним классом Person . А откуда появился файл BusinessObjects.class ?Если внимательно посмотреть на листинг 1, можно заметить, что код, который я написал в основном теле сценария после объявления этих трех классов, стал файлом .class, имя которого я указал после названия сценария. В этом случае, именем сценария было BusinessObjects.groovy , поэтому код, не содержащий определения класса, был скомпилирован в файл .class с названием BusinessObjects .Кодирование наоборотДекомпиляция этих классов может быть очень интересной. Получившиеся файлы .java будут значительно больше по размеру, благодаря природе скрытого кода Groovy; однако, вы, вероятно, заметили разницу между классами, объявленными в сценарии Groovy (например,Person ) и кодом вне классов (например, код BusinessObjects.class ). Классы, определенные в Groovy, завершаются реализацией GroovyObject , а код, расположенный за пределами класса, входит в класс, расширяющий Script .Например, если вы изучите файл .java, получившийся из BusinessObjects.class, вы увидите, что в нём определяется методы main() и run() . Очевидно, в методе run() содержится код, который я написал для создания новых экземпляров объектов, а метод main() вызывает метод run() .Суть этого вывода состоит в том, что чем лучше вы понимаете Groovy, тем проще будет встроить его в программы Java. "И зачем мне это нужно?" -- спросите вы? Итак, допустим, вы разработали что-то особенное в Groovy; правда, было бы неплохо встроить это также и в вашу программу на Java? Просто ради наглядности, я сначала попытаюсь создать в Groovy что-либо полезное, после чего я рассмотрю различные способы его внедрения в обычную программу Java. И снова музыка в GroovyЯ люблю музыку. В действительности моя коллекция компакт-дисков соревнуется по размерам с библиотекой книг по компьютерам. На протяжении многих лет я переписывал музыку на разные компьютеры и, по ходу дела, запутал свою коллекцию MP3 до предела - сегодня у меня множество каталогов, содержащих самую разнообразную музыку.Недавно я предпринял первые шаги к наведению порядка в моей музыкальной коллекции. Я написал небольшой сценарий Groovy, который циклически проходил по коллекции файлов MP3, содержащихся в папке, и предоставлял мне подробную информацию о каждом файле -- исполнитель, название альбома и т.п. Этот сценарий показан в листинге 3: Листинг 3. Очень полезный сценарий Groovy
Как вы можете видеть, сценарий очень прост, особенно учитывая его полезность в ситуации, подобной моей. Всё, что мне нужно делать, это передавать название определенной директории, и я получу нужную мне информацию (имя исполнителя, название песни и альбома) для каждого файла MP3 в этой директории. Теперь давайте посмотрим, что мне нужно сделать, чтобы внедрить этот отличный сценарий в обычную программу Java, которая может организовывать музыку с помощью базы данных или даже проигрывать MP3. Файлы классов и файлы классовКак я уже говорил выше, первый вариант -- это просто компиляция сценария с помощьюgroovyc . В этом случае я ожидаю, что groovyc создаст как минимум два файла .class -- один для класса Song и другой для кода сценария, следующего после объявления Song .На самом деле, groovyc создаст пять файлов .class. Это соотносится с тем фактом, что в Songs.groovy содержится три замыкания, два в методе getSongsForDirectory() и один в теле сценария, когда я формировал цикл по коллекции Song и вызывал println .Поскольку три файла .class фактически являются внутренними классами Song.class и Songs.class, мне нужно сконцентрироваться только на двух файлах .class. Song.class накладывается напрямую на объявление Song в сценарии Groovy и реализует GroovyObject , тогда как Songs.class представляет код сценария, приведенный после того, как я определил Song , и после этого расширяет Script .Теперь у меня есть два варианта внедрения только что скомпилированного кода Groovy в код Java: Я могу запускать код через метод main() , реализованный в файле класса Songs.class (поскольку он расширяет Script ), также я могу включать Song.class в путь классов и использовать его так же, как и любые другие объекты в коде Java.Будем прощеВызов файла Songs.class с помощью командыjava предельно прост, если вы не забываете включить зависимости Groovy и все возможные зависимости сценария Groovy. Самый простой способ включения необходимых классов Groovy состоит во включении в путь классов файлов jar "всё в одном", встраиваемых в Groovy. В моём случае, это файл groovy-all-1.0-beta-10.jar. Для запуска Songs.class мне также нужно не забыть включить используемую мной библиотеку MP3 (jid3lib-0.5.jar>), и поскольку я использую AntBuilder , мне также нужно включить в путь класса Ant . В листинге 4 всё сводится вместе:Листинг 4. Groovy через командную строку Java
Внедрение Groovy в код JavaНесмотря на то, что решение, работающее в командной строке, лёгкое и удобное, оно не универсально. Если бы мне было интересно перейти на более высокий уровень сложности, я мог бы импортировать мою MP3-утилиту непосредственно в программу Java. В этом случае я смог бы импортировать Song.class и использовать его так же, как и любой другой класс языка Java. Проблемы с путем классов будут такими же, как и раньше: мне нужно не забыть включить файл архива uber-Groovy ,Ant , и файл jid3lib-0.5.jar. В листинге 5 вы можете увидеть, как я импортировал MP3-утилиту Groovy в пример класса Java:Листинг 5. Встроенный код Groovy
Загрузчики классов GroovyВы думаете, что уже всё узнали? Оказывается, есть ещё несколько способов позабавиться с Groovy в Java. Помимо встраивания сценариев Groovy в программы Java с помощью прямой компиляции у меня также есть несколько вариантов встраивания непосредственно сценариев.Например, я могу с помощью GroovyClassLoader Groovy осуществить динамическую загрузку сценария Groovy и его исполнения, как показано в листинге 6:Листинг 6. GroovyClassLoader динамически загружает и исполняет сценарий Groovy
run() .Вы, наверное, помните, что мой сценарий Groovy также зависел от аргументов, передаваемых во время работы программы. Поэтому мне нужно настроить переменную args соответствующим образом, так как в данном случае я первым элементом установил название директории.Больше динамикиАльтернатива использованию компилированных классов и динамической загрузкеGroovyObject посредством загрузчиков классов состоит в использовании GroovyScriptEngine и GroovyShell для динамического выполнения сценариев Groovy.Внедрение объекта GroovyShell в обычные классы Java позволяет вам динамически выполнять сценарии Groovy так же, как это делает загрузчик класса. Кроме того, это даёт вам несколько возможностей запуска сценариев. В листинге 7 показано, как GroovyShell внедрен в обычный класс Java:Листинг 7. Внедрение GroovyShell
Как вы можете увидеть, сценарий Groovy запускается очень просто. Я просто создаю экземпляр GroovyShell , передаю название сценария и вызываю метод run() .Но это не всё. Если хотите, вы можете запросить экземпляр GroovyShell для типа Script вашего сценария. Используя тип Script , вы можете передавать объект Binding , содержащий все нужные параметры, и вызывать метод run() , как показано в листинге 8.Листинг 8. Забавляемся с GroovyShell
Механизм сценариев GroovyОбъектGroovyScriptEngine работает так же, как GroovyShell для динамически запускаемых сценариев. Отличие GroovyScriptEngine состоит в том, что при создании экземпляра вы можете указать ему несколько директорий, после чего вы в любое время можете вызвать несколько сценариев, как показано в листинге 9:Листинг 9. GroovyScriptEngine в действии
В листинге 9 я передаю массив, содержащий нужный мне путь, созданному экземпляру GroovyScriptEngine , создаю старый знакомый объект Binding и выполняю также знакомый сценарий Songs.groovy . Просто ради забавы, я запускаю сценарий BusinessObjects.groovy , который вы, возможно, помните из начала этого обсуждения.Среда сценариев BeanПоследним, но весьма важным, способом является среда сценариев Bean Scripting Framework (BSF) проекта Jakarta. Цель BSF - предложить общий API для внедрения любого языка сценариев, в том числе и Groovy, в обычное приложение Java. Этот стандартный, хотя, возможно, чрезмерно общий, подход позволяет вам внедрять сценарии Groovy без всяких усилий.Помните приведенный выше сценарий BusinessObjects ? В листинге 10 показано, как просто BSF позволяет вам встроить его в обычную программу Java:Листинг 10. BSF в работе
ЗаключениеЕсли что и ясно из этой статьи, так это то, что Groovy открывает множество вариантов повторного использования в коде Java. Во всех случаях, от компиляции сценариев Groovy в обычные старые файлы .class Java до динамической загрузки и запуска сценариев, главное, на что нужно обращать внимание - это гибкость и возможность совместной работы. Компиляция сценариев Groovy в обычные файлы .class - это простейший способ использования функций, которые вы встраиваете, тогда как динамическая загрузка сценариев упрощает добавление и изменение алгоритмов работы без затрат времени на компиляцию. (Конечно же, этот вариант работает только в том случае, если интерфейс не изменился.)Встраивание языков сценариев в обычный код Java не является повседневным явлением, но иногда такие возможности представляются. В приведенных здесь примерах я встраивал простую утилиту поиска по каталогам в приложение Java, которое может быть MP3-плеером или другой утилитой для работы с MP3. Несмотря на то, что я могу переписать мою утилиту поиска файлов MP3 в код Java, мне не нужно этого делать: Groovy великолепно совместим с языком Java, и, кроме того, я отлично позабавился, разбираясь со всеми возможностями! "Доктор Веб" обнаружил ботнет из более чем 550 тыс. "маков". Теория и практика Java: Пулы потоков и очередь действий (исходники). Сертифицированный специалист (Computerworld Россия, #01, 1999). Borland сообщила о планах развития JBuilder. ИТ-глоссарий. Главная » Java |
© 2024 Team.Furia.Ru.
Частичное копирование материалов разрешено. |