簡體   English   中英

使用 guice 動態注入通用對象

[英]Dynamically injecting generic objects with guice

我現在的情況:

我想將以下類注入到我的應用程序中:

public interface IConfigAccessor<T extends IConfig> {
    ...
}

ConfigAccessor是一個代理對象,在運行時動態創建。 這些對象的創建工作如下:

public class ConfigFactory implements IConfigFactory {
    private final IConfigUpdater updater;

    @Inject
    public ConfigFactory(IConfigUpdater updater) {
        this.updater = updater;
    }

    @Override
    public <T extends IConfig> IConfigAccessor<T> register(final String configKey, final Class<T> configClass) {    
        ConfigCache<T> configCache = new ConfigCache<>(new SomeOtherThings(), configKey, configClass);      
        updater.register(configCache);

        return new ConfigAccessor<>(configCache, configKey, configClass);
    }
}

如您所見,要創建這些對象,我需要注入ConfigUpdater和其他依賴項。 這意味着,該 guice 需要已經完全配置。

為了從 Guice 中獲取實例,我使用以下代碼:

IConfigFactory configClient = injector.getInstance(IConfigFactory.class);
IConfigAccessor<ConcreteConfig> accessor = configClient.register("key", ConcreteConfig.class)

我想如何通過 Guice 注入它們:

目前,我可以獲得所需的對象,但我必須在我的應用程序中手動傳遞它們。

相反,我想要的是以下內容:

public class SomeClass {
    @Inject
    public SomeClass(@Config(configKey="key") IConfigAccessor<ConcreteConfig> accessor) {
        // hurray!
    }
}

讓這個工作的正確方法/技術是什么?

經過大量研究,我對如何處理這個話題感到有點迷茫。 Guice 提供了很多不同的東西,包括簡單的Providers 、掃描類和識別自定義注釋的自定義ListenersFactoryModuleBuilders等等。

我的問題非常具體,我不確定要使用哪些東西以及如何使其工作。 我什至不確定 Guice 是否可以做到這一點?


編輯:到目前為止我所擁有的

我有以下要在構造函數參數中使用的注釋:

@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectConfig {
    String configKey();
}

在模塊內部,我可以將提供者綁定到 IConfigAccessor(使用上述注釋),如下所示:

bind(IConfigAccessor.class).annotatedWith(InjectConfig.class)
    .toProvider(new ConfigProvider<>());

但是,這有兩個問題:

  1. 提供者不能提供IConfigAccessor 要創建這樣的實例,提供程序需要一個IConfigUpdater ,但由於我為提供程序使用了“new”,因此無法注入它。
  2. 在提供者內部,無法找到 Annotation 中使用的configKey

第二種方法:

假設我已經知道我想在啟動期間注入的所有配置和 configKeys。 在這種情況下,我可以遍歷所有可能的 configKeys 並具有以下綁定:

String configKey = "some key";
final Class<? extends IConfig> configClass =...;      
bind(IConfigAccessor.class).annotatedWith(Names.named(configKey))
    .toProvider(new ConfigProvider<>(configKey, configClass));

但是,問題 (1) 仍然存在:提供程序無法獲取IConfigUpdater實例。

這里的主要問題是你不能在注入中使用注解的值。 還有一個問題涵蓋了這部分: Guice injection based on annotation value

您應該綁定提供者類,並通過注入 typeliteral 來獲取該類,而不是綁定提供者實例。

這樣,您的配置工廠看起來像這樣:

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);
    }
}

然后SomeClass:

public class SomeClass {
    @Inject
    public SomeClass(ConfigFactory<ConcreteConfig> accessor) {
        ConcreteConfig config = accessor.register("key");
    }
}

由於 SomeClass 無論如何都需要知道“密鑰”,因此這在信息方面並沒有太大的變化。 缺點是 SomeClass API 現在得到一個工廠而不是具體的配置。

[編輯]

這里有人實際上確實使用自定義注入注入了帶注釋的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM