【问题标题】:Writing custom Lombok Annotation handlers编写自定义 Lombok 注释处理程序
【发布时间】:2016-06-03 16:35:54
【问题描述】:

我想编写自定义的 Lombok Annotation 处理程序。我知道http://notatube.blogspot.de/2010/12/project-lombok-creating-custom.html。但是当前的 lombok jar 文件不包含很多 .class 文件,而是包含名为 .SCL.lombok 的文件。

我发现,.SCL.lombok 文件是 .class 文件,Lombok 的构建脚本在生成 jar 文件时确实重命名了它们,ShadowClassLoader 能够加载这些类 - 首字母缩略词 SCL 似乎从此而来。这样做的原因似乎只是为了“避免使用基于 SCL 的 jar 污染任何项目的命名空间。IDE 中的自动完成器不会建议任何实际公共 API 之外的内容。”

我只能通过

编译我的自定义处理程序
  • 解压 lombok.jar 的内容
  • 将 .SCL.lombok 文件重命名为 .class
  • 将生成的目录添加到编译类路径

此外,为了能够使用我的自定义处理程序,我需要创建一个新的 fat jar,其中包含 lombok 类和我的自定义处理程序。自定义 lombok 类加载器本质上阻止在其他多个 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", '$1.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)
}

【问题讨论】:

    标签: java lombok


    【解决方案1】:

    与此同时,Reinier Zwitserloot 创建了一个新的 git-branch sclExpansionUpdate,其中包含 ShadowClassLoader 的更新版本:

    ShadowClassLoader 现在对尝试扩展 lombok 更加友好。

    你的(单独的)jar/dir 应该有一个名为 META-INF/ShadowClassLoader。该文件应包含字符串 '龙目岛'。如果你有,该 jar/dir 中的任何类都将被加载 在与龙目岛课程相同的空间中。您还可以重命名课程 文件到 .SCL.lombok 以避免其他加载器找到它们。

    我猜这还没有进入主分支,因为它肯定没有经过太多测试 - 我只是自己尝试了一下,它包含一个小错误,阻止从扩展加载所需的 META-INF/服务.要修复它,您应该用inOwnBase 替换对partOfShadow 的两个方法调用:

    [... 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”不同的命名空间中拥有扩展注释处理程序和注释 - 很好!

    【讨论】:

    • 2年多过去了,还需要用inOwnBase()替换partOfShadow()的那两个方法调用吗? partOfShadow() 方法似乎将大部分工作委托给 inOwnBase() ,所以我看不到这种更改的好处。如果需要,那为什么?
    • 现在有一个拉取请求来修复 ShadowClassLoader 中的错误 github.com/rzwitserloot/lombok/pull/2204
    • 修复已经发布,Lombok 版本 1.18.10 的一部分
    【解决方案2】:

    使用来自这个问题和另一个答案(由 Balder)的输入,我们设法组合了一个自定义 Lombok 注释处理程序:Symbok。随意将其用作编写自己的示例。

    顺便说一句,您也可以实现javac plugin instead,而不是编写自定义的 Lombok 处理程序——它可能更简单。

    【讨论】:

      猜你喜欢
      • 2015-12-30
      • 2021-06-26
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 2020-02-14
      • 2020-10-17
      • 1970-01-01
      相关资源
      最近更新 更多