我有一堆第三方库,我包含在我的基础应用程序中.我无法控制那些第三方模块包含的支持库.这使我很难在我的应用程序中拥有相同版本的android支持库.
当我可以从每个依赖项中排除某些库时,我知道使用gradle:
compile('com.test:lib1:1.0.0') {
exclude group: 'com.android.support'
}
Run Code Online (Sandbox Code Playgroud)
然而,有大量的支持库,并将它们全部排除在我的第三方库的每一个看起来像是矫枉过正.
有没有更好的办法?
阅读这篇博文:https://www.devsbedevin.com/android-understanding-gradle-dependencies-and-resolving-conflicts/
它表明:
configurations.all {
resolutionStrategy {
preferProjectModules()
}
}
Run Code Online (Sandbox Code Playgroud)
但是当使用它时,我仍然在我的gradle文件中的Android Studio中收到警告,检测到有多个版本的支持库.
如果我的依赖项依赖于支持库的不同版本,我该怎么办?在上面的任何一种情况下,我都会强迫第三方库使用它们未构建的特定版本的支持库.我应该使用哪个版本?最新的支持库?Min支持所有第三方依赖的库?
这是一个最小的gradle文件示例,显示了第三方依赖项,每个依赖项依赖于它们自己的支持库版本.
android {
compileSdkVersion 26
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.example.app"
minSdkVersion 17
targetSdkVersion 25
}
}
configurations.all {
resolutionStrategy {
preferProjectModules()
}
}
dependencies {
compile 'com.android.support:support-v13:26.0.0'
compile 'com.test:lib1:1.0' // depends on support-v13:25.0.0
compile 'com.test:lib2:1.0' // depends on support-v13:25.2.0
compile 'com.test:lib3:1.0' // depends on support-v13:25.4.0
compile 'com.test:lib4:1.0' // depends on support-v13:26.0.0
}
Run Code Online (Sandbox Code Playgroud)
Android studio提供以下警告:
android dependency-management gradle android-studio android-gradle-plugin
我目前正在权衡DI和SL之间的优缺点.但是,我发现自己处于以下问题22中,这意味着我应该只使用SL作为一切,并且只在每个类中注入一个IoC容器.
DI Catch 22:
一些依赖项,如Log4Net,根本不适合DI.我称之为元依赖关系并认为它们对调用代码应该是不透明的.我的理由是,如果一个简单的类'D'最初是在没有记录的情况下实现的,然后增长到需要记录,那么依赖类'A','B'和'C'现在必须以某种方式获得这种依赖并将其从'A'到'D'(假设'A'组成'B','B'组成'C',依此类推).我们现在已经进行了重要的代码更改,因为我们需要登录一个类.
因此,我们需要一种不透明的机制来获取元依赖性.我想到了两个:Singleton和SL.前者具有已知的局限性,主要是关于刚性范围的能力:最好的是Singleton将使用存储在应用程序范围内的抽象工厂(即在静态变量中).这允许一些灵活性,但并不完美.
更好的解决方案是将IoC容器注入此类,然后使用该类中的SL从容器中解析这些元依赖关系.
因此,捕获22:因为类现在正在注入IoC容器,那么为什么不使用它来解析所有其他依赖项呢?
我非常感谢你的想法:)
c# singleton dependency-injection dependency-management service-locator
我使用maven-enforcer-plugin来检查依赖性收敛问题.典型的输出是:
[WARNING] Rule 1: org.apache.maven.plugins.enforcer.DependencyConvergence failed
with message:
Failed while enforcing releasability the error(s) are [
Dependency convergence error for junit:junit:3.8.1 paths to dependency are:
+-foo:bar:1.0-SNAPSHOT
+-ca.juliusdavies:not-yet-commons-ssl:0.3.9
+-commons-httpclient:commons-httpclient:3.0
+-junit:junit:3.8.1
and
+-foo:bar:1.0-SNAPSHOT
+-junit:junit:4.11
]
Run Code Online (Sandbox Code Playgroud)
看到这条消息,我通常会通过排除传递依赖来"解决"它,例如
<dependency>
<groupId>ca.juliusdavies</groupId>
<artifactId>not-yet-commons-ssl</artifactId>
<version>0.3.9</version>
<exclusions>
<!-- This artifact links to another artifact which stupidly includes
junit in compile scope -->
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我想了解这是否真的是一个解决方案以及以这种方式排除库的风险.照我看来:
如果我选择使用较新版本,"修复"通常是安全的.这依赖于库作者保持向后兼容性.
通常对Maven构建没有影响(因为更接近的定义获胜),但是通过排除依赖性我告诉Maven我知道这个问题并因此安抚maven-enforcer-plugin.
我的想法是否正确,是否有另一种处理此问题的方法?我对那些关注一般情况的答案感兴趣 - 我意识到junit上面的例子有点奇怪.
我点击F5~1000次并重新启动eclipse(也使用-clean),删除/ bin,但没有任何帮助.手动导入DoodleClient没有帮助.DoodleClient存在并且非常好,一切都在以前工作.点击"导入'DoodleClient'..."什么都不做.
在发生此问题之前我做了什么:
git rm *.class
假设我想在我的项目中添加guice-assistedinject作为依赖项.它将guice工件指定为依赖本身.如何告诉它使用no_aop版本的guice?
我知道我可以做到以下几点,但我可以一步完成而不排除guice模块吗?
dependencies {
compile (group: 'com.google.inject.extensions', name: 'guice-assistedinject', version: '3.0') {
exclude module: 'guice'
}
compile group: 'com.google.inject', name: 'guice', version: '3.0', classifier: 'no_aop'
}
Run Code Online (Sandbox Code Playgroud) java dependency-injection guice dependency-management gradle
如何将构造函数注入与"手动"构造函数参数组合?即.
public class SomeObject
{
public SomeObject(IService service, float someValue)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我的DI容器应该解析/注入IService,并且应该指定someValue.我该如何混合这两个?
是否有可能让leiningen直接从git存储库(在github上)作为依赖项拉出项目?
使用Bundler和Ruby,可以将gem映射到git repo,从而允许快速开发和集成依赖项目.
更新
根据公认的答案,现在有一个用于管理git-deps的leiningen插件:https: //github.com/tobyhede/lein-git-deps
我在我的POM中有一个依赖项需要设置为"提供",因此它不包含在编译中,但它仍然可以在我的项目中引用.当我去运行测试时,我希望相同的依赖项具有"test"范围,因此我不必手动将jar添加到我的类路径中.有没有办法做到这一点或取得类似的结果?
这背后的推理是我在JBOSS lib目录中提供了一些常见的jar,所以我想使用它们并保持它们的"提供"范围用于构建的战争.但是,当我从命令行运行JUnits时,我想使用存储库中的jar而不是手动将其添加到我的类路径中.
提前致谢
这是由Maven 2.2.1生成的依赖树
mvn -o dependency:tree -Dverbose -Dincludes=log4j
[INFO] [dependency:tree {execution: default-cli}]
[INFO] com.openboxes.renderingservice:common:jar:1.0
[INFO] +- org.springframework:spring:jar:2.0.4:compile
[INFO] | \- commons-logging:commons-logging:jar:1.1:compile
[INFO] | \- log4j:log4j:jar:1.2.12:compile
[INFO] \- it.mycompany.portal:server:jar:1.5-SNAPSHOT:compile
[INFO] \- org.slf4j:slf4j-log4j12:jar:1.1.0:compile
[INFO] \- (log4j:log4j:jar:1.2.13:compile - omitted for conflict with 1.2.12)
Run Code Online (Sandbox Code Playgroud)
正如您所见,log4j v1.2.12优于v1.2.13.
我知道"Maven通过最近赢的策略解决版本冲突"(参见http://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html)但这两个依赖关系似乎是在相同的距离(两个嵌套级别,我错了?)所以我希望使用最新的.
有人可以解释这个结果吗?
是的,log4j没有在这个POM中显式声明(我认为它应该是),但我想更好地理解Maven的工作方式.
谢谢
我目前正在尝试将Maven项目迁移到Gradle
在我的Maven版本中,我的所有依赖版本都在我的父 pom中列出如下:
<properties>
<spring.version>4.2.3.RELEASE</spring.version>
<spring.boot.version>1.3.3.RELEASE</spring.boot.version>
...
</properties>
Run Code Online (Sandbox Code Playgroud)
然后我可以在任何子模块中定义这样的依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我试图做同样的事情Gradle,因为我的一些模块共享依赖的版本是这样的,我不希望修改一个以上的地方,如果我想升级Spring或做类似的操作.
我得到的最接近的是:
dependencies {
ext.springVersion = '4.2.3.RELEASE'
compile "org.springframework:spring-jdbc:$springVersion"
}
Run Code Online (Sandbox Code Playgroud)
然而,这仍然不起作用.在Gradle中实现此目的的推荐方法是什么?或者Gradle对待这种方式有何不同?也许我对Maven的看法仍然太多,无法看到另一种解决方案.
请记住,对Gradle的尝试并不完全 是我想要的.我希望能够在一个单独的文件中定义依赖项,而不是直接在将使用它的文件上.