编写自定义 Lombok 注释处理程序
Writing custom Lombok Annotation handlers
我想编写自定义 Lombok 注释处理程序。我知道http://notatube.blogspot.de/2010/12/project-lombok-creating-custom.html。但是当前的lombok jar文件并不包含很多.class文件,而是包含名为.SCL.lombok的文件。
我发现,.SCL.lombok 文件是.class 文件,Lombok 的构建脚本在生成 jar 文件时确实重命名了它们,而 ShadowClassLoader 能够loading these classes -- 首字母缩写词 SCL 似乎来自于此。看来这样做的原因只是为了 "Avoid contaminating the namespace of any project using an SCL-based jar. Autocompleters in IDEs will NOT suggest anything other than actual public API."
我只能通过
编译自定义处理程序
- 解压 lombok.jar
的内容
- 将 .SCL.lombok 文件重命名为 .class
- 将生成的目录添加到编译 class路径
此外,为了能够使用我的自定义处理程序,我需要创建一个包含 lombok classes 和我的自定义处理程序的新 fat jar。自定义 lombok class 加载器基本上可以防止在其他多个 jar 中添加自定义处理程序。
这是扩展 Lombok 的唯一方法吗?还是我遗漏了什么?
我正在使用以下构建脚本
apply plugin: 'java'
repositories {
jcenter()
}
configurations {
lombok
compileOnly
}
def unpackedAndRenamedLombokDir = file("$buildDir/lombok")
task unpackAndRenameLombok {
inputs.files configurations.lombok
outputs.dir unpackedAndRenamedLombokDir
doFirst {
mkdir unpackedAndRenamedLombokDir
delete unpackedAndRenamedLombokDir.listFiles()
}
doLast {
copy {
from zipTree(configurations.lombok.singleFile)
into unpackedAndRenamedLombokDir
rename "(.*)[.]SCL[.]lombok", '.class'
}
}
}
sourceSets {
main {
compileClasspath += configurations.compileOnly
output.dir(unpackedAndRenamedLombokDir, builtBy: unpackAndRenameLombok)
}
}
tasks.compileJava {
dependsOn unpackAndRenameLombok
}
dependencies {
compile files("${System.properties['java.home']}/../lib/tools.jar")
compile "org.eclipse.jdt:org.eclipse.jdt.core:3.10.0"
compile 'javax.inject:javax.inject:1'
lombok 'org.projectlombok:lombok:1.16.6'
compileOnly files(unpackedAndRenamedLombokDir)
}
同时 Reinier Zwitserloot 创建了一个新的 git-branch sclExpansionUpdate, that contains an updated version of the ShadowClassLoader:
ShadowClassLoader is now friendlier to trying to extend lombok.
Your (separate) jar/dir should have a file named
META-INF/ShadowClassLoader. This file should contain the string
'lombok'. If you have that, any classes in that jar/dir will be loaded
in the same space as lombok classes. You can also rename the class
files to .SCL.lombok to avoid other loaders from finding them.
我想这还没有进入主分支,因为它肯定没有经过太多测试 - 我只是自己尝试了一下,它包含一个小错误,阻止加载所需的 META-INF/services从扩展。要修复它,您应该将对 partOfShadow
的两个方法调用替换为 inOwnBase
:
[... line 443]
Enumeration<URL> sec = super.getResources(name);
while (sec.hasMoreElements()) {
URL item = sec.nextElement();
if (!inOwnBase(item, name)) vector.add(item); // <<-- HERE
}
if (altName != null) {
Enumeration<URL> tern = super.getResources(altName);
while (tern.hasMoreElements()) {
URL item = tern.nextElement();
if (!inOwnBase(item, altName)) vector.add(item); // <<-- AND HERE
}
}
我用上面的修复程序测试了它,它似乎工作正常(虽然没有测试太多)。
旁注:有了这个新的扩展机制,现在终于可以在与 "lombok" 不同的命名空间中使用扩展注解处理程序和注解了 - 太好了!
使用来自这个问题和另一个答案(由 Balder 提供)的输入,我们设法组合了一个自定义 Lombok 注释处理程序:Symbok。随意使用它作为编写您自己的示例。
顺便说一句,除了编写自定义 Lombok 处理程序,您还可以实现一个 javac plugin instead —— 它可能更简单。
我想编写自定义 Lombok 注释处理程序。我知道http://notatube.blogspot.de/2010/12/project-lombok-creating-custom.html。但是当前的lombok jar文件并不包含很多.class文件,而是包含名为.SCL.lombok的文件。
我发现,.SCL.lombok 文件是.class 文件,Lombok 的构建脚本在生成 jar 文件时确实重命名了它们,而 ShadowClassLoader 能够loading these classes -- 首字母缩写词 SCL 似乎来自于此。看来这样做的原因只是为了 "Avoid contaminating the namespace of any project using an SCL-based jar. Autocompleters in IDEs will NOT suggest anything other than actual public API."
我只能通过
编译自定义处理程序- 解压 lombok.jar 的内容
- 将 .SCL.lombok 文件重命名为 .class
- 将生成的目录添加到编译 class路径
此外,为了能够使用我的自定义处理程序,我需要创建一个包含 lombok classes 和我的自定义处理程序的新 fat jar。自定义 lombok class 加载器基本上可以防止在其他多个 jar 中添加自定义处理程序。
这是扩展 Lombok 的唯一方法吗?还是我遗漏了什么?
我正在使用以下构建脚本
apply plugin: 'java'
repositories {
jcenter()
}
configurations {
lombok
compileOnly
}
def unpackedAndRenamedLombokDir = file("$buildDir/lombok")
task unpackAndRenameLombok {
inputs.files configurations.lombok
outputs.dir unpackedAndRenamedLombokDir
doFirst {
mkdir unpackedAndRenamedLombokDir
delete unpackedAndRenamedLombokDir.listFiles()
}
doLast {
copy {
from zipTree(configurations.lombok.singleFile)
into unpackedAndRenamedLombokDir
rename "(.*)[.]SCL[.]lombok", '.class'
}
}
}
sourceSets {
main {
compileClasspath += configurations.compileOnly
output.dir(unpackedAndRenamedLombokDir, builtBy: unpackAndRenameLombok)
}
}
tasks.compileJava {
dependsOn unpackAndRenameLombok
}
dependencies {
compile files("${System.properties['java.home']}/../lib/tools.jar")
compile "org.eclipse.jdt:org.eclipse.jdt.core:3.10.0"
compile 'javax.inject:javax.inject:1'
lombok 'org.projectlombok:lombok:1.16.6'
compileOnly files(unpackedAndRenamedLombokDir)
}
同时 Reinier Zwitserloot 创建了一个新的 git-branch sclExpansionUpdate, that contains an updated version of the ShadowClassLoader:
ShadowClassLoader is now friendlier to trying to extend lombok.
Your (separate) jar/dir should have a file named META-INF/ShadowClassLoader. This file should contain the string 'lombok'. If you have that, any classes in that jar/dir will be loaded in the same space as lombok classes. You can also rename the class files to .SCL.lombok to avoid other loaders from finding them.
我想这还没有进入主分支,因为它肯定没有经过太多测试 - 我只是自己尝试了一下,它包含一个小错误,阻止加载所需的 META-INF/services从扩展。要修复它,您应该将对 partOfShadow
的两个方法调用替换为 inOwnBase
:
[... line 443]
Enumeration<URL> sec = super.getResources(name);
while (sec.hasMoreElements()) {
URL item = sec.nextElement();
if (!inOwnBase(item, name)) vector.add(item); // <<-- HERE
}
if (altName != null) {
Enumeration<URL> tern = super.getResources(altName);
while (tern.hasMoreElements()) {
URL item = tern.nextElement();
if (!inOwnBase(item, altName)) vector.add(item); // <<-- AND HERE
}
}
我用上面的修复程序测试了它,它似乎工作正常(虽然没有测试太多)。
旁注:有了这个新的扩展机制,现在终于可以在与 "lombok" 不同的命名空间中使用扩展注解处理程序和注解了 - 太好了!
使用来自这个问题和另一个答案(由 Balder 提供)的输入,我们设法组合了一个自定义 Lombok 注释处理程序:Symbok。随意使用它作为编写您自己的示例。
顺便说一句,除了编写自定义 Lombok 处理程序,您还可以实现一个 javac plugin instead —— 它可能更简单。