2016-05-04 2 views
2

Я уже некоторое время использую guice, но недостаточно, чтобы выяснить, как выполнить то, что я хочу в этом случае. Мне кажется, что мне нужна комбинация AssistedInject, Throwing Providers и Multibindings, но я не уверен, как собрать все это вместе. Это сбитый код, который не совсем работает. Он должен быть Guicier!Именованные, метательные провайдеры инжектированных объектов

public class Utilities { 
    public static String expensiveLookup(String key) throws IOException {...} 
} 

public class Helper { 
    @Inject private InjectedClass injectedValue; 

    public Helper(String value1, String value2, String value3) {...} 
} 

public class Workhorse { 

    // This map isn't very guicy. I'd prefer named bindings, or a multibinding 
    private static Map<String, Helper> helpers = new HashMap(); 

    public static void register(String name, Helper helper) { 
     helpers.put(name, helper); 
    } 

    //////// 

    @Inject lots of things 

    public void doHardWork(String helperName) { 
     Helper helper = helpers.get(helperName); 
     // do something hard 
    } 
} 

class UserModule extends AbstractModule { 
    protected void configure() { 

     // Helpers are created with `new`, so they don't get `injectedValue` 
     Workhorse.register("cheap helper", new Helper("cheap value", ...)); 

     try { 
      // This expensive lookup should be delay until needed 
      String expensiveValue = Utilities.expensiveLookup("expensive key"); 
      Workhorse.register("expensive helper", new Helper(expensiveValue, ...)); 
     } catch (IOException ex) { 
      // This exception should be handled in `doHardwork()` 
     } 
    } 
} 

Я могу понять, как решить любые 2 из проблем сразу, но не все 4:

  • Helper сек должны быть созданы с Guice, не new
  • expensiveLookup должны быть задерживается, пока не потребуется
  • IOException должны быть перехвачены и обработаны doHardWork
  • helpers, вероятно, следует заменить на именованные привязки или многосвязную. Это не сложно для меня, но это кажется правильным.

Может кто-нибудь предложить какие-то намеки?

+0

Что такое value2 и value3 в вспомогательном конструкторе? это те значения, которые вы просматриваете с помощью ключа? или они произвольны во время выполнения? –

+0

Эти параметры также указаны в 'UserModule', но являются только строками. Нет необходимости в поиске. –

ответ

0

Ну, я, наконец, работал над решением. Я определенно не доволен этим, потому что он требует двойного кода и его трудно понять, но он работает. Я искренне надеюсь, что есть более простой способ.

public class Utilities { 
    public static String expensiveLookup(String key) throws IOException {...} 
} 

public class Helper { 
    private InjectedClass injectedValue; 

    @Inject 
    public Helper(
     @Assisted("value1") String value1, 
     @Assisted("value2") String value2, 
     @Assisted("value3") String value3, 
     InjectedClass injectedValue) { 

     this.injectedValue = injectedValue; 
     ... 
    } 

    public static <T extends Provider> void installProvider(
     Binder binder, String name, Class<T> providerClass) { 

     ThrowingProviderBinder.create(binder) 
      .bind(ProviderInterface.class, Helper.class) 
      .annotatedWith(Names.named(name)) 
      .to(providerClass) 
      .in(Singleton.class); 
    } 

    abstract public static Provider implements ProviderInterface { 
     @Inject private Factory factory; 

     protected Helper expensiveBuild(
      String expensiveKey, 
      String value2, 
      String value3) throws IOException { 

      String expensiveValue = Utilities.expensiveLookup(expensiveKey); 
      return cheapBuild(expensiveValue, value2, value3); 
     } 

     protected Helper cheapBuild(String value1, String value2, String value3) { 
      return Factory.create(value1, value2, value3); 
     } 
    } 

    interface ProviderInterface extends CheckedProvider<Helper> { 
     public Helper get() throws IOException; 
    } 

    interface Factory { 
     Helper create(
      @Assisted("value1") String value1, 
      @Assisted("value2") String value2, 
      @Assisted("value3") String value3); 
    } 
} 

class HelperModule exends AbstractModule { 
    protected void configure() { 
     install(new FactoryModuleBuilder() 
      .implement(Helper.class, Helper.class) 
      .build(Helper.Factory.class)); 
    } 
} 

public class Workhorse { 
    @Inject lots of things 
    @Inject private Injector injector; 

    public void doHardWork(String helperName) { 
     Key key = Key.get(Helper.ProviderInterface.class, Names.named(helperName)); 
     try { 
      Helper helper = injector.getInstance(key).get(helperName); 
      // do something hard 
     } catch (IOException ex) { 
      ... 
     } 
    } 
} 

class UserModule extends AbstractModule { 
    protected void configure() { 
     Helper.installProvider(binder(), "cheap helper", CheapProvider.class); 
     Helper.installProvider(binder(), "expensive helper", ExpensiveProvider.class); 
    } 

    private static class CheapProvider extends Provider { 
     public Helper get() { 
      return cheapBuild("cheap value", ...); 
     } 
    } 

    private static class ExpensiveProvider extends Provider { 
     public Helper get() throws IOException { 
      return expensiveBuild("expensive key", ...); 
     } 
    } 
} 

Мне бы очень понравилось, если бы у кого-то был лучший ответ!

Смежные вопросы