Java 如何使用两个安装公共依赖项模块的GUI模块
我正在从事一个由四部分组成的项目:Java 如何使用两个安装公共依赖项模块的GUI模块,java,guice,Java,Guice,我正在从事一个由四部分组成的项目: 将所有内容整合在一起的主项目。它包含publicstaticvoidmain(String…args)入口点 组件A 组件B A和B都参考的第三方通用组件 我使用Guice来处理所有四个部分之间的管道,这就是我的问题: 在As和Bs主GUI模块中,我安装了一个模块,该模块扩展了Common中定义的模块。在运行时,此安装程序失败,并出现以下错误: 已在common.AbstractCommonModule.configure()上配置了到common.Som
- 将所有内容整合在一起的
主项目。它包含
入口点publicstaticvoidmain(String…args)
- 组件
A
- 组件
B
和A
都参考的第三方B
组件通用
在
A
s和B
s主GUI模块中,我安装了一个模块,该模块扩展了Common
中定义的模块。在运行时,此安装程序失败,并出现以下错误:
已在common.AbstractCommonModule.configure()
上配置了到common.SomeClass
的绑定。[]
原因是我调用了common.AbstractCommonModule.configure()
两次;一次是从组件a
的com.a.MainModule.configure()
安装common.AbstractCommonPrivateModule
的子类实例,第二次是从组件B
的com.B.MainModule.configure()
安装
在Main
中只安装common.AbstractCommonPrivateModule
的一个实例不是一个选项,因为AbstractCommonPrivateModule
实现了一个特定的绑定方法BindComplexDuff(ComplexDuff)
,我只知道a
和B
中的参数,分别
我试图通过将A
和B
各自的主Guice模块包装在s中来解决这个问题。但是,此操作失败,出现下一个错误:
无法为%s创建绑定。它已在一个或多个子注入器或专用模块上配置%s%n如果它在专用模块中,是否忘记公开绑定?[]
在我的例子中,A
和B
各自的主Guice模块实际上是s-显然我可以从main
安装两次
如何绕过这些错误并安装两次AbstractCommonPrivateModule
模块?
编辑:我上传了一些示例代码(并解释了一些细节)而不是让
A
和B
安装Common
,让他们requireBinding()
为他们需要的类从Common
下载。然后依赖于A
或B
的模块也需要安装Common
。这可能有点奇怪,但实际上是可取的,因为a
和B
现在与Common
的耦合不那么紧密
更新 我之所以要安装两个Shiro模块,是因为我希望只使用一个Shiro配置(一个不支持密码保护资源的配置)来保护
ui
模块中的Jersey资源,而api
模块中的所有Jersey资源应使用完全不同的Shiro配置(仅将承载令牌理解为身份验证机制)进行保护
从广义上讲,这是难以解决的。GuiceInjector
为整个应用程序提供了一种做事的方式(通常是一个接口的一个实现);每个包没有不同的机制。您的两个Module
SwsApiServletModule和SwsUiServletModule
提供了许多相同的绑定,并且SwsModule
将它们一起安装。本质上,您说的是“Guice,请提供基于承载令牌的身份验证机制”,然后紧接着说“Guice,请提供基于密码的身份验证机制”。它只能做一个或另一个,因此它不会随意选择一个,而是失败得很快
当然,有很多解决方案,具体取决于您的需求。最常见的是使用和让UI和API代码请求不同的注释。这样,您就可以为同一接口或类安装两个不同的实现(具有不同的注释)
下面是一个例子:
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());
}
}
您在评论中提到,您无法控制正在安装的重叠绑定,因为它们来自第三方模块。如果是这样的话(我没有看到你的代码中发生了什么),出于安全原因,第三方可能不希望你做你想做的事情。例如
简单地绑定基于密码的机制可能会在整个应用程序中引入漏洞。也许值得尝试更好地理解第三方打算如何使用他们的模块
另一个不理想但适用于某些用例的选项是使用两个完全独立的Injector
实例,每个实例具有一个绑定。然后手动将需要的实例直接传递给UI和API代码。这有点违背了Guice的目的,但并不总是错误的决定。使用可以减少痛苦
另外,您的“示例代码”非常庞大,可能超过90%与问题无关。将来,请花时间创建一个只包含与当前问题相关的代码的。任何人都无法通过筛选100多个Java文件和7300多行代码来理解您的问题。这不仅会使试图帮助您的人更容易,而且只要尝试创建一个演示问题的SSCCE通常就足以帮助您自己理解和解决问题。要安装两次相同的模块,重写模块中的
.equals
方法以引用类而不是对象相等。Guice不会安装与已安装模块相同的模块。这并不重要
install new AbstractCommonPrivateModule();
@Override
public boolean equals(Object obj) {
return obj != null && this.getClass().equals(obj.getClass());
}
// Override hashCode as well.
@Override
public int hashCode() {
return this.getClass().hashCode();
}