Java 如何在匕首2中添加未知数量的未知模块?

Java 如何在匕首2中添加未知数量的未知模块?,java,dagger-2,Java,Dagger 2,我有几个在编译时不知道的模块(想想“插件”)。它们都实现了一个“标记”接口MyModule:公共接口MyModule{} 多亏了ServiceLoader和@AutoService,我才实例化了它们 如何将它们全部添加到组件生成器中 Dagger 2作者认为这个问题与StackOverflow有关。我不相信这是真的,因为它看起来像是一个遗漏的用例,但好吧,我在这里告诉他们怀疑的好处,并将其发布 我知道我可以使用Guice或Dagger 1,但正如Dagger 2团队的门票上所说;我不想要任何反射

我有几个在编译时不知道的模块(想想“插件”)。它们都实现了一个“标记”接口
MyModule
公共接口MyModule{}

多亏了
ServiceLoader
@AutoService
,我才实例化了它们

如何将它们全部添加到组件生成器中

Dagger 2作者认为这个问题与StackOverflow有关。我不相信这是真的,因为它看起来像是一个遗漏的用例,但好吧,我在这里告诉他们怀疑的好处,并将其发布


我知道我可以使用Guice或Dagger 1,但正如Dagger 2团队的门票上所说;我不想要任何反射(bar
ServiceLoader
),Dagger1现在已经被弃用了。另外,建议切换到Dagger 2(这就是为什么我试图将Dagger 1项目升级到Dagger 2的原因)。

目前这是不可能的,也是不可能的。见项目概述的开头一句(重点):

Dagger是一个完全静态的编译时依赖注入框架,适用于Java和Android

当您要求您的对象图处理任意标记接口模块时,您阻止Dagger知道它将访问哪个@提供的方法,这就剥夺了Dagger在编译时检查和连接组件的能力。因此,要使Dagger像您所说的那样支持您的用例,它必须逆转许多核心体系结构决策以及编译时检查和代码生成的优势。虽然我不是Dagger团队的成员,但我认为在可预见的未来,这将使其不适合,我认为这是您的问题被标记为按预期工作的部分原因


也就是说,有许多方法可以使用多个共存组件(每个插件一个)在核心应用程序中使用静态分析和代码生成,同时支持任意数量的插件。例如,如果您的插件有一组可预测的依赖项,您可以创建一个
新的插件模块(PluginFactory…factoriesToSupport)
,该模块将提供一个
@集合createPluginSet(Dep1 Dep1,Dep2 Dep2)
,以在插件工厂中迭代并返回一组插件。此外,如果插件依赖项代表了顶级组件的很大一部分,并且构建图支持它,那么可以将组件本身注入@Provides方法,然后让单独构建的PluginFactory实例遵从它们自己的(生成的静态分析代码)使用Dagger组件生成插件实例。简而言之,只要您在Dagger中,您就需要遵循Dagger的编译时分析规则,但在这些限制条件下,您仍然可能找到可行的解决方案。

模块是否都为集合或映射提供相同类型的对象?模块之间是否存在依赖关系?(一个模块取决于另一个模块中声明的绑定)在我看来,您选择使用dagger模块定义插件是一个错误的决定,应该使用清晰/干净的插件API进行重构(可能使用
@Component(dependencies=PluginDeps.class)
在插件中依赖于应用程序公开的内容;然后通过将插件传递给新组件中的模块,将插件重新注入匕首图中)。瞧,我觉得您更愿意重新思考您的问题,而不是匕首(可能只是一种可能的解决方案,也可能不是)。插件需要访问注入的对象。是的,一些插件之间存在依赖关系。在匕首1中效果很好。我在指南中使用了类似的原则。我不明白为什么插件用例会被扔进垃圾箱。钩子是成套的,是的。它们需要访问注入对象,还是需要访问任意未知注入对象。由于组件本身是提供给注入点的,所以完全可以设置一个干净的插件API,为插件提供服务,并有一个
@Provides@ElementsIntoSet-scannedPlugins(PluginAPI){/*do-ServiceLocator-lookup and-initialization*/}
或将整个应用程序组件本身注入该方法,并使hte插件初始化机制接收该信息。我已经开始在MOE工具中这样做了。不是全部,但很有希望。您建议的解决方案(
PluginModule
)不允许我为插件提供核心对象,如果它们需要它们作为参数。我没有得到的是匕首1和匕首2之间的根本变化(我认为)是一个最小的增益:匕首1的性能非常出色,而匕首2并没有真正提高性能。这是一种我在被迫从版本1迁移到版本2时不希望出现的不兼容(“被迫”,因为Dagger 1从9月15日起就被弃用了)。在我检查之前,我需要几天的时间来完全处理这个问题。@Olivier通过
@Provides
方法参数访问您的组件(或其子集),您可以提供这些核心对象,但需要注意的是,它们可能需要在接口上显式可用,并通过组件依赖关系传播。在这个评论框中,我无法对Dagger 2破坏兼容性的更改的优点进行辩论,但我要说的是,性能不一定是唯一的因素,例如,我理解并感谢你的宝贵意见。如果我正确理解您的建议(将所有依赖项作为单个接口方法的参数提供),那么不兼容的处理就是一个破坏交易的行为。目前,我强烈考虑在内部分叉匕首1,以及它所暗示的所有后果。我们必须在内部讨论这个问题,因为它改变了我们的整个结构(据我所知,我读到的内容包含了我不喜欢的内容)。如果只有几个依赖项,我建议单独传递它们,但所有组件都可以传入