- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个现有的对象层次结构,其中一些对象具有需要注入(inject)的字段。还有一些其他对象是使用 Google Guice 构造的并且需要注入(inject)对先前描述的对象层次结构中某些对象的引用。我如何使用 Guice 进行此类注入(inject)?
问题在于现有层次结构中的对象不是使用 Guice 构造的,因此默认情况下不受注入(inject)过程的约束。当然,injector.injectMembers()
方法能够注入(inject)现有对象实例,但它不适用于对象层次结构。
对于那些想知道为什么我不能使用 Guice 构建提到的对象层次结构的人。此层次结构表示 GUI 对象,由 GUI 框架 ( Apache Pivot ) 根据声明性 GUI 描述构建(事实上,此过程可以描述为对象反序列化)。这样接口(interface)构造就相当简单,我只想将某些服务引用注入(inject)接口(interface)对象,反之亦然(用于回调)。
我目前将要采用的方法如下所述。
为了注入(inject)到预先存在的对象层次结构中,只需让所有对注入(inject)感兴趣的对象实现特定接口(interface),例如:
public interface Injectable {
void injectAll(Injector injector);
}
然后那些对象会像这样实现这个接口(interface):
public void injectAll(Injector injector) {
injector.injectMembers(this);
for (Injectable child : children)
child.injectAll(injector);
}
然后我只需为层次结构中的根对象调用 mainWindow.injectAll(injector)
并注入(inject)所有感兴趣的对象。
不是很好的解决方案,但可以在一方面完成工作。另一方面,我需要从这个层次结构中注入(inject)对象。我想这可以通过为此类对象实现自定义提供程序来完成。
我的问题有更好的解决方案吗?也许我的方法也有问题?
最佳答案
此解决方案可行,但我想向您推荐一个略有不同的解决方案。
具体来说,由于您要遍历一个深层对象结构,这看起来确实像是访问者模式的工作。此外,您所描述的似乎需要一个双阶段注入(inject)器:一个“引导”阶段可以注入(inject)数据透视创建的层次结构所需的东西(但不能注入(inject)任何数据透视创建的元素)和第二阶段这是您的应用程序使用的真正注入(inject)器(可以注入(inject)任何东西)。
我建议的是这个基本模式:创建一个遍历层次结构的访问者,并且随着它的进行,它会注入(inject)那些需要它的东西,并记录那些需要在别处注入(inject)的东西。然后,当它完成访问所有内容时,它使用 Injector.createChildInjector
制作一个新的 Injector
可以从原始 Injector
注入(inject)东西和东西来自枢轴创建的层次结构。
首先定义一个可以访问这个层次结构中所有内容的访问者:
public interface InjectionVisitor {
void needsInjection(Object obj);
<T> void makeInjectable(Key<T> key, T instance);
}
然后为所有 pivot 创建的元素定义一个接口(interface):
public interface InjectionVisitable {
void acceptInjectionVisitor(InjectionVisitor visitor);
}
您将在 pivot 创建的类中实现此接口(interface)(假设此代码在 FooContainer
类中):
public void acceptInjectionVisitor(InjectionVisitor visitor) {
visitor.needsInjection(this);
visitor.makeInjectable(Key.get(FooContainer.class), this);
for (InjectionVisitable child : children) {
child.acceptInjectionVisitor(visitor);
}
}
请注意,前两个语句是可选的 - 可能是枢轴层次结构中的某些对象不需要注入(inject),也可能是您以后不希望其中的一些对象可注入(inject)。另外,请注意 Key
的使用 - 这意味着如果您希望某些类可以使用特定注释注入(inject),您可以执行以下操作:
visitor.makeInjectable(Key.get(Foo.class, Names.named(this.getName())), this);
现在,您如何实现 InjectionVisitor
?方法如下:
public class InjectionVisitorImpl implements InjectionVisitor {
private static class BindRecord<T> {
Key<T> key;
T value;
}
private final List<BindRecord<?>> bindings = new ArrayList<BindRecord<?>>();
private final Injector injector;
public InjectionVisitorImpl(Injector injector) {
this.injector = injector;
}
public void needsInjection(Object obj) {
injector.injectMemebers(obj);
}
public <T> void makeInjectable(Key<T> key, T instance) {
BindRecord<T> record = new BindRecord<T>();
record.key = key;
record.value = instance;
bindings.add(record);
}
public Injector createFullInjector(final Module otherModules...) {
return injector.createChildInjector(new AbstractModule() {
protected void configure() {
for (Module m : otherModules) { install(m); }
for (BindRecord<?> record : bindings) { handleBinding(record); }
}
private <T> handleBinding(BindRecord<T> record) {
bind(record.key).toInstance(record.value);
}
});
}
}
然后在您的 main
方法中使用它作为:
PivotHierarchyTopElement top = ...; // whatever you need to do to make that
Injector firstStageInjector = Guice.createInjector(
// here put all the modules needed to define bindings for stuff injected into the
// pivot hierarchy. However, don't put anything for stuff that needs pivot
// created things injected into it.
);
InjectionVisitorImpl visitor = new InjectionVisitorImpl(firstStageInjector);
top.acceptInjectionVisitor(visitor);
Injector fullInjector = visitor.createFullInjector(
// here put all your other modules, including stuff that needs pivot-created things
// injected into it.
);
RealMainClass realMain = fullInjector.getInstance(RealMainClass.class);
realMain.doWhatever();
请注意,createChildInjector
的工作方式可确保如果您有任何 @Singleton
绑定(bind)在注入(inject)到数据透视层次结构中的东西,您将获得相同的实例注入(inject)通过您的真实注入(inject)器 - 只要 firstStageInjector
能够处理注入(inject),fullInjector
就会将注入(inject)委托(delegate)给 firstStageInjector
。
编辑添加:一个有趣的扩展(如果你想深入研究 Guice 魔法)是修改 InjectionImpl
以便它记录你的源代码中调用 makeInjectable 的地方
。这样,当您的代码不小心告诉访问者有关绑定(bind)到同一键的两个不同事物时,您可以从 Guice 中获得更好的错误消息。为此,您需要将 StackTraceElement
添加到 BindRecord
,记录 new RuntimeException().getStackTrace()[1]
的结果> 在方法 makeInjectable
中,然后将 handleBinding
更改为:
private <T> handleBinding(BindRecord<T> record) {
binder().withSource(record.stackTraceElem).bind(record.key).toInstance(record.value);
}
关于java - 如何使用 Guice @Inject 到现有对象层次结构中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2856004/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!