метапрограммирование Грааля - PullRequest
8 голосов
/ 25 мая 2010

Насколько я понимаю, в приложении Grails есть два очевидных места, где можно заниматься метапрограммированием:

  1. init закрытие Bootstrap.groovy
  2. doWithDynamicMethods закрытие плагина

Мета-программирование, о котором я здесь говорю, должно быть видно во всем приложении, типичные примеры включают добавление (или замену) методов сторонних классов.

String.metaClass.myCustomMethod = { /* implementation omitted */ }

Недостатком (1) является то, что метапрограммирование не будет применяться, когда приложение динамически перезагружается. Недостаток (2) заключается в том, что мне нужно создать и поддерживать весь плагин только ради небольшого метапрограммирования.

Есть ли лучшее место для такого рода метапрограммирования?

Обновление

Следуя предложенному Тедом ниже, я добавил следующий класс к src/groovy

package groovy.runtime.metaclass.java.lang

/**
 * Adds custom methods to the String class
 */
class StringMetaClass extends DelegatingMetaClass {

    StringMetaClass(MetaClass meta) {
        super(meta)
    }

    Object invokeMethod(Object object, String method, Object[] arguments) {
        if (method == 'hasGroovy') {
            object ==~ /.*[Gg]roovy.*/
        } else {
            super.invokeMethod object, method, arguments
        }
    }
}

Затем перезапустил приложение и запустил следующий код в консоли Grails:

assert 'mrhaki loves Groovy'.hasGroovy()

Я получил следующее исключение

groovy.lang.MissingMethodException: No signature of method:
java.lang.String.hasGroovy() is applicable for argument types: () values: []

Я делаю что-то не так или есть причина, по которой это не работает в приложении Grails?

Ответы [ 3 ]

2 голосов
/ 26 мая 2010

Посмотрите на Делегирование MetaClass , оно является частью groovy и делает ваш метакласс изменения частью метакласса, который используется в каждом экземпляре этого класса с самого начала. Он работает по простому соглашению и даже работает за пределами Grails.

1 голос
/ 04 июля 2012

Вы можете использовать решение DelegatingMetaClass, но его нужно упаковать в файл JAR, а затем добавить в каталог lib.

Создайте новый каталог со следующим файлом сборки Gradle:

apply plugin: 'groovy'
repositories.mavenCentral()
dependencies { groovy: 'org.codehaus.groovy:groovy-all:1.8.6' }

В каталоге src / main / groovy вы можете разместить исходный код StringMetaClass. С помощью $ gradle jar вы можете создать файл JAR, а затем скопировать его в каталог lib своего приложения Grails.

1 голос
/ 25 мая 2010

В зависимости от вашего варианта использования Groovy AST-преобразования являются третьим вариантом. Преобразование AST - это модификации байт-кода во время компиляции. Они доступны с Groovy 1.6 и были значительно улучшены в Groovy 1.7. Особенно ASTBuilder - это очень элегантный способ.

Помните, что использование AST в Grails может потребовать внесения некоторых изменений в сборку. Классы, выполняющие AST, должны быть скомпилированы перед классами, на которые распространяется AST. Это можно легко сделать, подключившись к событию «CompileStart» в scripts / _Events.groovy и предварительно скомпилировав Transformation.

...