Если вы пользовались системой сборки Gradle, то, вероятно, уже применяли и извлекали пользу из DSL-возможностей языка Groovy. В этой статье давайте рассмотрим такой пример.
Возьмем следующий фрагмент DSL из конфигурации Gradle.
plugins { id 'java' }
В разделе plugins настраиваются плагины Gradle, используемые в вашей сборке, и упоминаются все плагины, которые вы хотите применить. Давайте разберемся, что происходит под капотом, чтобы добиться работоспособности, с помощью не очень сложного примера.
def plugins (def pluginConfig) { println "Plugins called" } //--------------- DSL plugins { id 'java' }
Когда мы запускаем приведенный выше код, то видим, что в консоли выводится «Plugins called» (вызываемые плагины). Мы понимаем, что plugins — это метод. Посмотрите на альтернативный способ вызова метода plugins.
plugins({ id 'java' })
Теперь понятно, что содержимое внутри ‘{}’ передается в качестве аргумента методу plugins. Такие блоки кода в Groovy называются closures. Если последний аргумент вашего метода (он может быть и единственным) является замыканием (closure), Groovy позволяет писать их вне круглых скобок. Таким образом, приведенный выше код можно записать следующим способом.
plugins() { id 'java' }
Кроме того, Groovy позволяет опускать круглые скобки, если метод имеет хотя бы один аргумент, что и произошло в данном случае. Таким образом, мы получаем оригинальный код, используемый в нашем DSL.
plugins { id 'java' }
Поскольку мы хотим добавить плагины в проект, давайте создадим структуру для хранения информации о нем.
class Project { List<Plugin> plugins = [] } import groovy.transform.ToString @ToString(includePackage = false) class Plugin { String id }
Теперь нам осталось создать экземпляр класса Plugin и добавить его в plugins Project. Как вы уже догадались, id 'java' означает, что мы вызываем метод идентификации с ‘java’ в качестве аргумента. Давайте добавим этот метод в класс Project, поскольку он кажется подходящим местом для его размещения.
class Project { List<Plugin> plugins = [] def id(String pluginId) { println "Adding plugin $pluginId" plugins << new Plugin(id: pluginId) } }
Давайте обновим наш метод плагинов, чтобы вызвать замыкание на инстансе project.
def plugins(def pluginConfig) { Project project = new Project() println "Plugins called" project.with pluginConfig }
В консоли должно появиться сообщение «Adding plugin java» (Добавление плагина java). Здесь мы используем метод with, чтобы обеспечить замыкание, которое мы получили в качестве аргумента, для объекта ‘project’ (а не для инстанса этого скрипта).
Давайте добавим еще один плагин в наш DSL и убедимся, что он работает так, как ожидалось. Заодно отобразим все плагины из проекта.
def plugins(def pluginConfig) { Project project = new Project() println "Plugins called" project.with pluginConfig println project.plugins } //--------------- plugins{ id 'java' id 'groovy' }
На консоли вы должны увидеть следующее:
Plugins called Adding plugin java Adding plugin groovy [Plugin(java), Plugin(groovy)]
Конечно, полноценный DSL будет более сложным. Здесь я попытался передать суть идеи с помощью максимально простых примеров.
В заключение приглашаем всех желающих на открытое занятие «Shared Libraries в Jenkins», которое пройдет завтра в 20:00. На этом уроке посмотрим, как расширять пайплайны в Jenkins с помощью внешних библиотек и научимся их писать. Урок будет особенно полезен DevOps-инженерам и Java-разработчикам, которые хотят научиться создавать и настраивать сборки Java Backend проектов.
ссылка на оригинал статьи https://habr.com/ru/companies/otus/articles/743980/
Добавить комментарий