是否可以检查哪些 gradle 依赖项包含给定的类?

Posted

技术标签:

【中文标题】是否可以检查哪些 gradle 依赖项包含给定的类?【英文标题】:Is it possible to check which gradle dependencies contains given class? 【发布时间】: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 中搜索所有依赖项(包括传递的依赖项)以查找特定的完全限定类名?这样我们就可以当场解决这些问题。

【问题讨论】:

【参考方案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

以上是关于是否可以检查哪些 gradle 依赖项包含给定的类?的主要内容,如果未能解决你的问题,请参考以下文章

使用变量时如何在 build.gradle 中查看依赖项更新?

Maven 检查存储库中更新的依赖项

Maven 检查存储库中更新的依赖项

基于ssm框架没有pom.xml正常吗

Gradle:下载包含的 aar 库的依赖项

是否可以让 gradle 解析像 '5.0.+' 这样的 ivy 依赖项以获得像 '5.0.0.1.12.24' 这样的版本?