【问题标题】:Is it possible to check which gradle dependencies contains given class?是否可以检查哪些 gradle 依赖项包含给定的类?
【发布时间】:2018-09-16 10:37:10
【问题描述】:

最近我们遇到了 org.apache.commons.beanutils.PropertyUtilsBean 类的版本不匹配问题。我们认为不匹配只是在版本 1.8 和 1.9.3 中带来 commons-beanutils 的某些依赖项之间,但在跟踪并排除每个传递依赖项之后,我们仍然面临一个问题。

事实证明,PropertyUtilsBean 也被打包在 commons-digester3-3.2-with-deps 中,而不是声明为对 commons-beanutils 的依赖。

是否可以在 gradle 中搜索所有依赖项(包括传递的依赖项)以查找特定的完全限定类名?这样我们就可以当场解决这些问题。

【问题讨论】:

    标签: java gradle dependencies dependency-management


    【解决方案1】:

    我试过了,可以使用一些自定义的 gradle 构建逻辑:

    Kotlin DSL

    tasks {
      val searchClass by creating {
        doLast {
          configurations.forEach {    // check all configurations
            if (it.isCanBeResolved) { 
              try {
                val classLoader = configToClassloader(it)
                // replace here class you are looking for
                val cl = Class.forName("arrow.core.Either", false, classLoader)
                println("found in Configuration $it")
                println(cl.protectionDomain.codeSource.location)
              } catch (e: Exception) {}
            }
          }
        }
      }
    }
    
    // Helper function: convert a gradle configuration to ClassLoader
    fun configToClassloader(config: Configuration) = 
      URLClassLoader(
        config.files.map {
          it.toURI().toURL()
        }.toTypedArray())
    

    这可以通过用一些参数机制替换硬编码的类名来进一步增强。

    样本输出:

    > Task :searchClass
    Configuration configuration ':domain:apiDependenciesMetadata'
    file:/Users/abendt/.gradle/caches/modules-2/files-2.1/io.arrow-kt/arrow-core-data/0.9.0/a5b0228eebd5ee2f233f9aa9b9b624a32f84f328/arrow-core-data-0.9.0.jar   
    

    Groovy DSL

    def configToClassloader(config) {
      return new URLClassLoader(
              *config.files.collect {
                  it.toURI().toURL()
              }.toArray())
    }
    
    task searchClass {
      doLast {
        configurations.forEach {    // check all configurations
            if (it.canBeResolved) {
                try {
                    def classLoader = configToClassloader(it)
                    // replace here class you are looking for
                    def cl = Class.forName("arrow.core.Either", false, classLoader)
                    println("found in Configuration $it")
                    println(cl.protectionDomain.codeSource.location)
                } catch (e) {}
            }
        }
      }
    }
    

    编辑:我最近创建了一个提供所描述任务的 Gradle 插件:https://plugins.gradle.org/plugin/io.github.redgreencoding.findclass

    【讨论】:

    • 这看起来很有希望,但是您在这里使用的是什么语言?
    • 这是 Gradle Kotlin DSL。也可以使用 Groovy 来实现
    • 我也添加了一个基于 Goovy 的示例
    【解决方案2】:

    你可以这样做

    task findJarsForClass {
       doLast {
          def findMe = 'org/apache/commons/beanutils/PropertyUtilsBean.class'
          def matches = configurations.runtime.findAll { f ->
             f.name.endsWith('.jar') && 
                !(zipTree(f).matching { include findMe }.empty) 
          }
          println "Found $findMe in ${matches*.name}"
       } 
    }
    

    【讨论】:

      【解决方案3】:

      只需ctrl+左键点击导入的类名,就可以在ide上看到jar了(eclipse有这个功能,可能IntelliJ也有)

      【讨论】:

      • 这就是我们找到它的方式,但我很好奇是否有 Gradle 特定的解决方案。
      【解决方案4】:

      尝试使用任务dependencyInsight

      gradle -q dependencyInsight --configuration compile --dependency commons-beanutils
      

      每个 Gradle 项目都提供了 task dependencyInsight 来渲染 来自命令行的所谓依赖洞察报告。给定一个 依赖关系图中的依赖关系,您可以识别选择 原因并追踪依赖选择的来源。

      【讨论】:

      • 在这种情况下,我想在任何依赖项中查找特定类。类似yum provides
      猜你喜欢
      • 2018-05-30
      • 1970-01-01
      • 2011-01-15
      • 2020-09-05
      • 2014-08-07
      • 2014-11-30
      • 1970-01-01
      • 2011-08-26
      • 2019-04-11
      相关资源
      最近更新 更多