gpt4 book ai didi

java - 如何使用安装公共(public)依赖模块的两个 Guice 模块

转载 作者:IT老高 更新时间:2023-10-28 20:54:13 25 4
gpt4 key购买 nike

我正在做一个由四个部分组成的项目:

  • 将所有内容组合在一起的 Main 项目。这包含 public static void main(String... args) 入口点。
  • 组件A
  • 组件B
  • AB 都引用的第 3 方 Common 组件。

我正在使用 Guice 作为所有四个部分之间的管道,这是我的问题:
AB 的主要 Guice 模块中,我安装了一个扩展了 Common 中定义的模块。在运行时,此设置失败并出现以下错误:

A binding to common.SomeClass was already configured at common.AbstractCommonModule.configure(). [source]

原因是我调用了 common.AbstractCommonModule.configure() 两次;一次通过从组件 Acom.a.MainModule.configure() 安装 common.AbstractCommonPrivateModule 的子类实例,第二次来自组件 Bcom.b.MainModule.configure()

Main 中仅安装 一个 common.AbstractCommonPrivateModule 实例不是一种选择,因为 AbstractCommonPrivateModule 实现了一个具体的 binder 方法 bindComplicatedStuff(ComplicatedStuff),我只知道 AB 内部的参数。

我尝试通过将 AB 各自的主要 Guice 模块包装在 PrivateModule 中来解决整个问题。 s。但是,这失败了,出现下一个错误:

Unable to create binding for %s. It was already configured on one or more child injectors or private modules %s%n If it was in a PrivateModule, did you forget to expose the binding? [source]

在我的例子中,AB 各自的主要 Guice 模块实际上是 ServletModule s - 显然我 可以Main 安装两次。

我怎样才能绕过这些错误并安装 AbstractCommonPrivateModule 模块两次?

编辑:我上传了一些示例代码(带有一些细节的解释)to GitHub

最佳答案

不要让 AB 安装 Common,而是让它们 requireBinding() 用于类他们需要来自Common。那么依赖AB 的模块也需要安装Common。这可能感觉有点奇怪,但实际上是可取的,因为 AB 现在与 Common 的耦合不那么紧密了。


更新

The reason I am installing two ShiroWebModules is because I want the Jersey resources in the ui module to only be secured using one Shiro configuration (one that unserstands password-protecting resources), while all Jersey resources in the api module should be be secured using an entirely different Shiro configuration (one that understands only bearer tokens as an authentication mechanism).

从广义上讲,这是棘手的。 Guice Injector 为整个应用程序提供了一种做某事的方式(通常是接口(interface)的一种实现);每个包没有不同的机制。您的两个 ModuleSwsApiServletModuleSwsUiServletModule 提供了许多相同的绑定(bind),而 SwsModule 将它们安装在一起。本质上,您是在说“Guice,请提供基于承载 token 的身份验证机制”,然后紧接着说“Guice,请提供基于密码的身份验证机制”。它只能做一个或另一个,所以它不会随意选择一个,而是快速失败。

当然,有多种解决方案,具体取决于您的具体需求。最常见的是使用binding annotations并让 UI 和 API 代码请求不同的注释。这样你就可以安装同一个接口(interface)或类的两个不同的实现(带有不同的注解)。

这是一个例子:

package api;

public class ApiResources {
@Inject
public ApiResources(@ApiAuthMechanism AuthMechanism auth) {
this.auth = auth;
}
}

---

package api;

public class ApiModule implements Module {
public void configure() {
bind(AuthMechanism.class).annotatedWith(ApiAuthMechanism.class)
.to(BearerTokenAuthMechanism.class);
}
}

---

package ui;

public class UiResources {
@Inject
public UiResources(@UiAuthMechanism AuthMechanism auth) {
this.auth = auth;
}
}

---

package ui;

public class UiModule implements Module {
public void configure() {
bind(AuthMechanism.class).annotatedWith(UiAuthMechanism.class)
.to(PasswordAuthMechanism.class);
}
}

---

package webap;

public class WebappModule implements Module {
public void configure() {
// These modules can be installed together,
// because they don't install overlapping bindings
install(new ApiModule());
install(new UiModule());
}
}

您在评论中提到您无法控制正在安装的重叠绑定(bind),因为它们来自第三方模块。如果是这种情况(我没有看到您的代码中发生了这种情况),出于安全原因,第三方可能不希望您做您想做的事情。例如,简单地绑定(bind)基于密码的机制可能会在整个应用程序中引入漏洞。可能值得尝试更好地了解第三方打算如何使用他们的模块。

另一种不理想但适用于某些用例的选项是使用两个完全独立的 Injector 实例,每个绑定(bind)一个。然后你手动将你需要的实例直接传递给 UI 和 API 代码。这在某种程度上违背了 Guice 的目的,但这并不总是错误的决定。使用 child Injectors可以减轻这种痛苦。


顺便说一句,您的“示例代码”非常庞大,可能超过 90% 与问题无关。以后请花时间创建 SSCCE仅包含与手头问题相关的代码。根本没有任何人会筛选 100 多个 Java 文件和 7,300 多行代码来理解您的问题。这不仅会使试图帮助您的人更容易,而且只需尝试创建一个展示问题的 SSCCE 通常就足以帮助您自己理解和解决问题。

关于java - 如何使用安装公共(public)依赖模块的两个 Guice 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33857582/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com