2017-06-26 1 views
-1

Si un objet (appelons-le workController) contient une carte de chaîne pour les gestionnaires (Map<String, Handler> handlerMap) qui est injecté à il utilise le mapBinder dans le module Guice et d'autres variables d'instance qui sont également injectées. Maintenant, si je veux instancier workController dans mon code (laissez-nous dire que je suis en train de créer un fournisseur pour workConsumer: workConsumerProvider qui dépend de workController et donc je dois instancier cela et fournir workController au constructeur de workConsumer), devrais-je déclarer à nouveau la carte entière et la passer au constructeur de workController ou y a-t-il un autre moyen d'y parvenir?Comment instancier un objet qui contient une variable d'instance de la carte qui a été instancié à l'aide du liant carte dans Guice

Tenir compte WorkController.java:

public class WorkController implements ActivityController { 

private ObjectMapper objectMapper; 

private final Map<String, Handler> handlerMap; 

@Inject 
public WorkController(final ObjectMapper objectMapper, 
         final Map<String, Handler> handlerMap) { 
    this.objectMapper = objectMapper; 
    this.handlerMap = handlerMap; 
} 

public void control() { 
//call the handler = getHandler(string usecase) 
//call the handler.handle() 
} 

public Handler getHandler(String useCase) { 
    Handler handler = eventHandlerMap.get(useCase); 
    return handler; 
} 

Pour soutenir DI pour workController, j'ai défini le fournisseur pour ObjectMapper comme suit: ObjectMapperProvider.java

public class ObjectMapperProvider implements Provider<ObjectMapper> { 

    @Override 
    public ObjectMapper get() { 
     final ObjectMapper mapper = new ObjectMapper(); 
     return mapper; 
    } 
} 

La carte est injecté à l'intérieur du Guice correspondant module utilisant MapBinder comme suit:

public class WorkConsumerModule extends AbstractModule { 

    @Override 
    protected void configure() { 

     bind(WorkConsumer.class).toProvider(WorkConsumerProvider.class); 

     bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class); 

     final MapBinder<String, handler> mapBinder = MapBinder.newMapBinder(binder(), 
      String.class, handler.class); 

     //other bindings for the subject and events to be added here. 

     mapBinder.addBinding(UseCaseOne.toString()).to(HandlerImplOne.class); 

     mapBinder.addBinding(UseCaseTwo.toString()).to(HandlerImplTwo.class); 

    } 

} 

Non w, pensez WorkConsumer.java

public class WorkConsumer { 

    @Inject 
    public WorkConsumer(final String instanceVariableOne, 
         final String instanceVariableTwo, 
         final String instanceVariableThree, 
         final WorkController workController) { 

     final FailureHandler failureHandler = new FailureHandlerImpl(); 
     final Consumer consumer = new Consumer(instanceVariableOne, instanceVariableTwo, instanceVariableThree, workController, failureHandler); 
     consumer.start(); 
    } 
} 

Maintenant, afin d'injecter les chaînes variables exemple pour cette WorkConsumer, nous créons un WorkConsumerProvider classe: WorkConsumerProvider.java

public class WorkConsumerProvider implements Provider<WorkConsumer> { 

    @Override 
    public WorkConsumer get() { 
     final WorkConsumer workconsumer 
        = new WorkConsumer(getInstanceVariableOne(),                     
             getInstanceVariableTwo(),     
             getInstanceVariableThree(),     
             getWorkController()); 
    return workconsumer; 
} 

private String getInstanceVariableOne() { 
    //return these values based on configs. 
} 

private String getInstanceVariableTwo() { 
    //return these values based on configs. 
} 

private String getInstanceVariableThree() { 
    //return these values based on configs. 
} 

//This is the place where I have a doubt. 
private WorkController getWorkController() { 
//Should I declare a new map and populate it again in order to instantiate workController despite having populated it once inside the guice module workConsumerModule.java ? 
//I haven't yet populated it here. 
    return new WorkController(new ObjectMapper(), new HashMap<String, Handler>()); 
} 

}

+1

Je pense que [du code montrant ce que vous avez essayé] (https://stackoverflow.com/help/mcve) pour atteindre votre objectif aiderait à répondre à votre question. – Markus

+1

Extraits de code ajoutés. – kakarot

+0

Votre exemple pourrait être simplifié, mais juste pour que vous sachiez que vous n'avez pas besoin de 'ObjectMapperProvider' tel quel. Les [Just in Time Bindings] de Guice (https://github.com/google/guice/wiki/JustInTimeBindings) le trouveront et l'instancieront pour vous car il a un constructeur sans argument sans avoir besoin d'une liaison ou d'un fournisseur. –

Répondre

1

Vous pouvez injecter dans vos fournisseurs afin de pouvoir injecter un WorkController entièrement construit et instancié.

public class WorkConsumerProvider implements Provider<WorkConsumer> { 

    private final WorkController controller; 

    @Inject 
    WorkConsumerProvider(WorkController controller) { 
     this.controller = controller; 
    } 

    @Override 
    public WorkConsumer get() { 
     return new WorkConsumer(
      /* instance variables */, 
      controller 
     ); 
    } 

    //Your instance variables 
} 

Cela entraînera chaque WorkConsumer de partager un WorkController.

Si vous souhaitez que chacun d'eux possède un WorkController unique, vous pouvez remplacer la variable d'instance par Provider<WorkController> et l'injecter. Ensuite, utilisez controllerProvider.get() dans WorkConsumerProvider#get().

Guice's wiki a beaucoup de bonnes informations, y compris les meilleures pratiques et des exemples pour différents scénarios.