Java 用guice动态注入通用对象 我目前的情况:

Java 用guice动态注入通用对象 我目前的情况:,java,guice,Java,Guice,我想将以下类注入到我的应用程序中: public interface IConfigAccessor<T extends IConfig> { ... } 如您所见,要创建这些对象,我需要插入ConfigUpdater和其他部门。这意味着,guice需要已经完全配置好 为了从Guice中获取实例,我使用以下代码: IConfigFactory configClient = injector.getInstance(IConfigFactory.class); IConfig

我想将以下类注入到我的应用程序中:

public interface IConfigAccessor<T extends IConfig> {
    ...
}
如您所见,要创建这些对象,我需要插入
ConfigUpdater
和其他部门。这意味着,guice需要已经完全配置好

为了从Guice中获取实例,我使用以下代码:

IConfigFactory configClient = injector.getInstance(IConfigFactory.class);
IConfigAccessor<ConcreteConfig> accessor = configClient.register("key", ConcreteConfig.class)
在模块内部,我可以将提供程序绑定到IConfigAccessor(使用上述注释):


但是,问题(1)仍然存在:提供程序无法获取
IConfigUpdater
实例。

这里的主要问题是无法在注入中使用注释的值。这一部分还有另一个问题:

您不应该绑定提供程序实例,而应该绑定提供程序类,并通过获取该类

这样,您的配置工厂可以如下所示:

public class ConfigFactory<T extends IConfig> implements IConfigFactory {
    @Inject private final IConfigUpdater updater;
    @Inject private TypeLiteral<T> type;
    @Override
    public IConfigAccessor<T> register(final String configKey) {    
        Class<T> configClass = (Class<T>)type.getRawType();
        ConfigCache<T> configCache = new ConfigCache<>(new SomeOtherThings(), configKey, configClass);      
        updater.register(configCache);

        return new ConfigAccessor<>(configCache, configKey, configClass);
    }
}
公共类ConfigFactory实现IConfigFactory{
@注入私有最终IConfigUpdater更新程序;
@注入私有TypeLiteral类型;
@凌驾
公共IConfigAccessor寄存器(最终字符串configKey){
类configClass=(类)类型。getRawType();
ConfigCache ConfigCache=new ConfigCache(new SomeOtherThings(),configKey,configClass);
寄存器(configCache);
返回新的ConfigAccessor(configCache、configKey、configClass);
}
}
然后是一些课程:

public class SomeClass {
    @Inject
    public SomeClass(ConfigFactory<ConcreteConfig> accessor) {
        ConcreteConfig config = accessor.register("key");
    }
}
公共类SomeClass{
@注入
公共类(ConfigFactory访问器){
ConcreteConfig=accessor.register(“key”);
}
}
因为有些类无论如何都需要知道“key”,所以这并不是一个非常明智的更改信息。缺点是SomeClass API现在获得的是一个工厂,而不是具体的配置

[编辑]


是一个确实使用自定义注入注入了带注释的值的人。

副本中有将使您达到目的的所有功能的示例。@JarrodRoberson谢谢。如果我正确理解了其他问题(特别是),Guice就不可能做到这一点。当我想在构造函数中注入这些对象时,我需要实现一个提供者。但是,这是不可能的,因为我无法将“configKey”从注释获取到提供程序中。在使用侦听器时,我自己有效地管理注入,但随后无法在构造函数中使用它。我说的对吗?@JarrodRoberson但是,我也不能使用自定义注释,因为我首先无法构造要注入的对象(
ConfigAccessor
)。在TypeListener中,我无法从Guice(
IConfigUpdater
)@JarrodRoberson注入其他对象,因此最终,这一切归结为“我无法在模块内部创建要注入
ConfigAccessor
的对象,因为我需要注入器。如果我在运行时(在拥有注入器之后)创建对象,我将需要注入器。”,我再也不能自己注入它们了。你把这件事弄得太复杂了。
提供程序
用于注入模块中不可用的东西,更具体地说,需要已经创建
注入器
。这涵盖了自Guice 10年前首次问世以来我遇到的所有合理情况!如果这并不意味着你需要重新评估你在做什么。
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectConfig {
    String configKey();
}
bind(IConfigAccessor.class).annotatedWith(InjectConfig.class)
    .toProvider(new ConfigProvider<>());
String configKey = "some key";
final Class<? extends IConfig> configClass =...;      
bind(IConfigAccessor.class).annotatedWith(Names.named(configKey))
    .toProvider(new ConfigProvider<>(configKey, configClass));
public class ConfigFactory<T extends IConfig> implements IConfigFactory {
    @Inject private final IConfigUpdater updater;
    @Inject private TypeLiteral<T> type;
    @Override
    public IConfigAccessor<T> register(final String configKey) {    
        Class<T> configClass = (Class<T>)type.getRawType();
        ConfigCache<T> configCache = new ConfigCache<>(new SomeOtherThings(), configKey, configClass);      
        updater.register(configCache);

        return new ConfigAccessor<>(configCache, configKey, configClass);
    }
}
public class SomeClass {
    @Inject
    public SomeClass(ConfigFactory<ConcreteConfig> accessor) {
        ConcreteConfig config = accessor.register("key");
    }
}