Связанный с Guice провайдер не используется для выполнения зависимостей - PullRequest
2 голосов
/ 15 марта 2012

Я пытаюсь использовать внедрение поставщика для внедрения предварительно сконфигурированного объекта на фабрику:

public class CacheBuilderProvider 
    implements Provider<CacheBuilder<Object, Object>> {
    public CacheBuilder<Object, Object> get () {
        //Log the cache builder parameters before creation

        CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder();
        //configure the cacheBuilder
        return cacheBuilder;
    }
}

public class MyCacheFactory {
    private final CacheBuilder<Object, Object> cacheBuilder;

    @Inject
    public MyFactory(CacheBuilder<Object, Object> cacheBuilder) {
        this.cacheBuilder = cacheBuilder;
    }
}

public class CacheModule extends AbstractModule {            
    @Override
    protected void configure() {
        bind(CacheBuilder.class)
            .toProvider(CacheBuilderProvider.class)
            .in(Singleton.class);
        bind(MyCacheFactory.class)
            .in(Singleton.class);
    }
}

Когда я использую инжектор для получения экземпляра MyCacheFactory, я не получаю вывод журнала иненастроенный экземпляр CacheBuilder<Object, Object>;ни одна из моих настроек не была применена.Установка точек останова подтверждает, что провайдер никогда не используется.

Я также пытался применить @Named("MyCacheBuilder") к соответствующим элементам:

public class CacheBuilderProvider 
    implements Provider<CacheBuilder<Object, Object>> {
    @Named("MyCacheBuilder")
    public CacheBuilder<Object, Object> get () { //... }
}

public class MyCacheFactory {
    //...

    @Inject
    public MyFactory(
        @Named("MyCacheBuilder") 
        CacheBuilder<Object, Object> cacheBuilder
    ) {
        //... 
    }
}

Когда я пытаюсь запустить этот код, я получаюa CreationException:

1) No implementation for com.google.common.cache.CacheBuilder
annotated with @com.google.inject.name.Named(value=MyCacheBuilder) was bound.

Я также пробовал различные комбинации необработанных и общих ссылок на типы в объявлениях класса и конструктора, но без дополнительного успеха.

Я могу обойти этопросто создав провайдера и связав экземпляр, возвращенный из get() сам, но я ожидаю (и deisre), что Guice сделает это за меня.

Что-то не так (или очевидно) не так с моей настройкой?

1 Ответ

2 голосов
/ 16 марта 2012

Это может сработать:

bind(new TypeLiteral<CacheBuilder<Object, Object>>() {})
          .annotatedWith(Names.named("MyCacheBuilder"))
          .toProvider(CacheBuilderProvider.class)
          .in(Singleton.class);

Волшебство здесь - это класс TypeLiteral, чью документацию по Javadoc вы должны прочитать. По сути, это способ связывания с универсальным типом (CacheBuilder<Object, Object> в вашем случае). Это волшебство необходимо, потому что Java реализует обобщенные типы, используя стирание, поэтому вы не можете просто написать CacheBuilder<Object, Object>.class.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...