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

Java 是否可以检查哪个gradle依赖项包含给定的类?,java,gradle,dependencies,dependency-management,Java,Gradle,Dependencies,Dependency Management,最近,我们遇到了一个类org.apache.commons.beanutils.PropertyUtilsBean的版本不匹配问题。我们认为不匹配只是在版本1.8和1.9.3中带来的commons beanutils之间的一些依赖,但是在跟踪并排除每个可传递依赖之后,我们仍然面临一个问题 事实证明,PropertyUtilsBean也被封装在commons-digester3-3.2-with-deps中,而不是声明为对commons beanutils的依赖关系 在gradle中是否可以搜索所

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

事实证明,PropertyUtilsBean也被封装在
commons-digester3-3.2-with-deps
中,而不是声明为对
commons beanutils
的依赖关系

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

只需按住ctrl键并左键单击导入的类名,然后您就可以在ide上看到jar(eclipse具有该功能,可能IntelliJ也具有该功能)

尝试使用以下任务:

每个Gradle项目都提供任务依赖性Insight来呈现 来自命令行的所谓依赖性洞察报告。给予 依赖关系在依赖关系图中,您可以标识所选内容 推理并跟踪依赖项选择的来源


我试过了,可以使用一些定制的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())
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) {}
        }
    }
  }
}
这可以通过使用一些参数机制替换硬编码的类名来进一步增强

样本输出:

> 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

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())
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) {}
        }
    }
  }
}
你可以这样做

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}"
   } 
}

这就是我们找到它的方式,但我很好奇是否有Gradle特定的解决方案。在这种情况下,我想在任何依赖项中寻找特定的类。类似于
yum提供的
这似乎很有希望,但您在这里使用的是什么语言呢?是Gradle-Kotlin DSL。也可以使用Groovy实现。我还添加了一个基于Goovy的示例