Guice:在创建模块之前实例化一个单例
Guice: instantiating a singleton before creating the module
是否可以在创建 Module 之前使用 Guice 实例化一个单例并将其分配给一个引用,然后将该实例传递给 Module 构造函数以在配置期间绑定?
这是我的意思的一个例子:
我有一个方法允许我根据接口的自定义实现创建对象,该接口作为 Optional 在构造函数中传递(如果用户不提供自定义实现,我们将使用默认实现),这是通过将接口绑定到模块 class 中的特定实现来完成。 :
public static MyClass createMyClassObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
SpecialInterface specialInterfacebject;
if(customSpecialInterfaceObject.isPresent() {
specialInterfaceObject = customSpecialInterfaceObject.get()
} else {
/* here I would like to bind it to an instance of the DefaultSpecialInterfaceObject but can't really do something like:
Injector injector = Guice.createInjector(myClassModule);
DefaultSpecialInterface instance = injector.getInstance(DefaultSpecialInterface.class);
as the module is yet to be created */
}
MyClassModule myClassModule = new MyClassModule(specialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
return injector.getInstance(MyClass.class);
}
我目前正在使用 classes 而不是实例来解决这个问题,例如下面的示例,但我不太喜欢这个解决方案。很高兴看到更好的方法:
private static Class resolveSpecialInterfaceObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
Class specialInterfaceObjectClass;
if (customSpecialInterfaceObject.isPresent()) {
specialInterfaceObjectClass= customSpecialInterfaceObject.get().getClass();
} else {
specialInterfaceObjectClass = DefaultSpecialInterface.class;
}
return specialInterfaceObjectClass;
}
public abstract class MyClassModule extends AbstractModule {
private final Class<SpecialInterface> specialInterfaceObjectClass;
public MyClassModule(Class<SpecialInterface> specialInterfaceObjectClass) {
this.specialInterfaceObjectClass= specialIntefaceObjectClass;
}
@Override
protected void configure() {
bind(SpecialInterface.class).to(specialInterfaceObjectClass);
}
}
编辑,来自下面的评论:
one more thing- didn't want to make the question too long; actually, I also want to perform another operation on the resulting instance of SpecialInterface, but only if it is the instance of DefaultSpecialInterface and I don't think it should be done in the Module. I was thinking if I could just have this bean up and running before, such as in Spring, so I could just pass it to the Module, but also use it in another method call before?
你能把整个 Optional
拿走并使用 bind(...).toInstance(...)
吗?
public static MyClass createMyClassObject(
Optional<SpecialInterface> customSpecialInterfaceObject) {
MyClassModule myClassModule = new MyClassModule(customSpecialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
MyClassFactory instance = injector.getInstance(MyClassFactory.class);
return instance.createMyClassObject();
}
class MyClassModule extends AbstractModule {
private final Optional<SpecialInterface> customObject;
MyClassModule(Optional<SpecialInterface> customObject) {
this.customObject = customObject;
}
@Override public void configure() {
if (customObject.isPresent()) {
// Singleton by necessity: Guice doesn't know how to create another one.
bind(SpecialInterface.class).toInstance(customObject.get());
} else {
// Default scoped. Add ".in(Singleton.class)" if necessary.
bind(SpecialInterface.class).toInstance(DefaultSpecialInterfaceClass.class);
}
}
}
如果您只想对 DefaultSpecialInterface 执行额外的初始化,您有多种选择:
如果某种初始化对所有实现都很重要并且可能太重而无法放入 class 构造函数,请在您的 SpecialInterface 上添加一个 initialize
方法。使自定义成为空操作,并为 DefaultSpecialInterface 实现它。
如果初始化是 DefaultSpecialInterface 独有的,我看不出为什么它不应该在模块中。编写 @Provides
方法或绑定到 Provider<SpecialInterface>
以正确创建和初始化 DefaultSpecialInterface。
如果您的真正目标是将业务逻辑保留在模块之外,您可以通过将其提取到 是 [=35] 的独立 Provider 或 DefaultSpecialInterfaceFactory 中来实现=]对此负责。
请记住,Guice 负责将完全构造的对象提供给您的对象图中,这意味着注入 SpecialInterface 应该得到 SpecialInterface 通用契约的现成可用实现程序。如果 Guice 需要执行一些初始化来实现这一点,让它这样做并不是没有道理的,而且模块是一个不错的地方。
是否可以在创建 Module 之前使用 Guice 实例化一个单例并将其分配给一个引用,然后将该实例传递给 Module 构造函数以在配置期间绑定?
这是我的意思的一个例子: 我有一个方法允许我根据接口的自定义实现创建对象,该接口作为 Optional 在构造函数中传递(如果用户不提供自定义实现,我们将使用默认实现),这是通过将接口绑定到模块 class 中的特定实现来完成。 :
public static MyClass createMyClassObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
SpecialInterface specialInterfacebject;
if(customSpecialInterfaceObject.isPresent() {
specialInterfaceObject = customSpecialInterfaceObject.get()
} else {
/* here I would like to bind it to an instance of the DefaultSpecialInterfaceObject but can't really do something like:
Injector injector = Guice.createInjector(myClassModule);
DefaultSpecialInterface instance = injector.getInstance(DefaultSpecialInterface.class);
as the module is yet to be created */
}
MyClassModule myClassModule = new MyClassModule(specialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
return injector.getInstance(MyClass.class);
}
我目前正在使用 classes 而不是实例来解决这个问题,例如下面的示例,但我不太喜欢这个解决方案。很高兴看到更好的方法:
private static Class resolveSpecialInterfaceObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
Class specialInterfaceObjectClass;
if (customSpecialInterfaceObject.isPresent()) {
specialInterfaceObjectClass= customSpecialInterfaceObject.get().getClass();
} else {
specialInterfaceObjectClass = DefaultSpecialInterface.class;
}
return specialInterfaceObjectClass;
}
public abstract class MyClassModule extends AbstractModule {
private final Class<SpecialInterface> specialInterfaceObjectClass;
public MyClassModule(Class<SpecialInterface> specialInterfaceObjectClass) {
this.specialInterfaceObjectClass= specialIntefaceObjectClass;
}
@Override
protected void configure() {
bind(SpecialInterface.class).to(specialInterfaceObjectClass);
}
}
编辑,来自下面的评论:
one more thing- didn't want to make the question too long; actually, I also want to perform another operation on the resulting instance of SpecialInterface, but only if it is the instance of DefaultSpecialInterface and I don't think it should be done in the Module. I was thinking if I could just have this bean up and running before, such as in Spring, so I could just pass it to the Module, but also use it in another method call before?
你能把整个 Optional
拿走并使用 bind(...).toInstance(...)
吗?
public static MyClass createMyClassObject(
Optional<SpecialInterface> customSpecialInterfaceObject) {
MyClassModule myClassModule = new MyClassModule(customSpecialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
MyClassFactory instance = injector.getInstance(MyClassFactory.class);
return instance.createMyClassObject();
}
class MyClassModule extends AbstractModule {
private final Optional<SpecialInterface> customObject;
MyClassModule(Optional<SpecialInterface> customObject) {
this.customObject = customObject;
}
@Override public void configure() {
if (customObject.isPresent()) {
// Singleton by necessity: Guice doesn't know how to create another one.
bind(SpecialInterface.class).toInstance(customObject.get());
} else {
// Default scoped. Add ".in(Singleton.class)" if necessary.
bind(SpecialInterface.class).toInstance(DefaultSpecialInterfaceClass.class);
}
}
}
如果您只想对 DefaultSpecialInterface 执行额外的初始化,您有多种选择:
如果某种初始化对所有实现都很重要并且可能太重而无法放入 class 构造函数,请在您的 SpecialInterface 上添加一个
initialize
方法。使自定义成为空操作,并为 DefaultSpecialInterface 实现它。如果初始化是 DefaultSpecialInterface 独有的,我看不出为什么它不应该在模块中。编写
@Provides
方法或绑定到Provider<SpecialInterface>
以正确创建和初始化 DefaultSpecialInterface。如果您的真正目标是将业务逻辑保留在模块之外,您可以通过将其提取到 是 [=35] 的独立 Provider 或 DefaultSpecialInterfaceFactory 中来实现=]对此负责。
请记住,Guice 负责将完全构造的对象提供给您的对象图中,这意味着注入 SpecialInterface 应该得到 SpecialInterface 通用契约的现成可用实现程序。如果 Guice 需要执行一些初始化来实现这一点,让它这样做并不是没有道理的,而且模块是一个不错的地方。