我想在编译时修改我的一些Grails域类。我最初认为这是Groovy全球ASTTransformation的工作,因为我不想注释我的域类(本地转换器需要)。最好的方法是什么?
我还尝试模仿DefaultGrailsDomainClassInjector.java在同一个包中创建我自己的类,实现相同的接口,但我可能只是不知道如何在正确的位置打包它,因为我从未见过我的方法被调用。
另一方面,我能够手动创建一个 JAR,其中包含一个编译的 AST 转换类,以及普通 Groovy 全局转换所需的 META-INF/服务工件。我将那个JAR扔到我项目的"lib"目录中,然后访问()被成功调用。显然,这是一项草率的工作,因为我希望将我的 AST 转换的源代码放在 Grails 插件中,并且如果不需要的话,不需要单独的 JAR 工件,而且我无法通过将 JAR 放在我的 Grails 插件的"库"中来让这种方法工作,但不得不将其放入 Grails 应用程序的"库"中。
这篇文章也有一点帮助:Grails 2.1.1 - 如何使用AstTransformer开发插件?
关于全局转换的事情 转换代码在编译开始时应该可用。把变压器放在罐子里是我首先做的!但正如你所说,这是一项草率的工作。您要做的是在其他人进入编译阶段之前编译您的 ast 转换类。这就是你的工作!
准备变压器
src
文件夹中创建一个名为 precompiled
的目录! 并添加 Transformation 类和转换器在此目录中使用的具有正确打包结构的类(如注释)。
然后在名为 precompiled/META-INF/services
中创建一个名为 org.codehaus.groovy.transform.ASTTransformation
的文件,您将拥有以下结构。
precompiled
--amanu
----LoggingASTTransformation.groovy
--META-INF
----services
------org.codehaus.groovy.transform.ASTTransformation
然后在 org.codehaus.groovy.transform.ASTTransformation
文件中写入转换器的完全限定名,对于上面的示例,将amanu.LoggingASTTransformation
完全限定名
实现
package amanu
import org.codehaus.groovy.transform.GroovyASTTransformation
import org.codehaus.groovy.transform.ASTTransformation
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.control.SourceUnit
@GroovyASTTransformation(phase=CompilePhase.CANONICALIZATION)
class TeamDomainASTTransformation implements ASTTransformation{
public void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
println ("*********************** VISIT ************")
source.getAST()?.getClasses()?.each { classNode ->
//Class node is a class that is contained in the file being compiled
classNode.addProperty("filed", ClassNode.ACC_PUBLIC, new ClassNode(Class.forName("java.lang.String")), null, null, null)
}
}
}
汇编
实现这一点后,您可以通过两种方式离开!第一种方法是把它放在罐子里,就像你一样!另一种是先于别人使用时髦的脚本编译它。为了在圣杯中做到这一点,我们使用_Events.groovy
脚本。
您可以从插件或主项目中执行此操作,没关系。如果不存在,请创建一个名为 _Events.groovy
的文件并添加以下内容。
代码是从修改后从 reinhard-seiler.blogspot.com 复制的
eventCompileStart = {target ->
...
compileAST(pluginBasedir, classesDirPath)
...
}
def compileAST(def srcBaseDir, def destDir) {
ant.sequential {
echo "Precompiling AST Transformations ..."
echo "src ${srcBaseDir} ${destDir}"
path id: "grails.compile.classpath", compileClasspath
def classpathId = "grails.compile.classpath"
mkdir dir: destDir
groovyc(destdir: destDir,
srcDir: "$srcBaseDir/src/precompiled",
classpathref: classpathId,
stacktrace: "yes",
encoding: "UTF-8")
copy(toDir:"$destDir/META-INF"){
fileset(dir:"$srcBaseDir/src/precompiled/META-INF")
}
echo "done precompiling AST Transformations"
}
}
前面的脚本将在编译其他脚本之前编译转换器!这使转换器可用于转换域类。
别忘了
如果使用类路径中添加的类以外的任何类,则还必须预编译这些类。上面的脚本将编译 precompiled
目录中的所有内容,您还可以添加不需要 ast 但在该目录中需要它的类!
如果要在转换中使用域类,则可能需要在evenCompileEnd
块中进行预编译!但这会使事情变慢!
更新
@Douglas Mendes提到过,有一种简单的方法可以进行预编译。哪个更简洁。
eventCompileStart = {
target -> projectCompiler.srcDirectories.add(0, "./src/precompiled")
}