Guice / DI and injection mixing and parameters transmitted during operation

I have a situation where I initialize some of my classes, some of the fields that I need to enter (e.g. links to factories, etc.), while some others are dynamic and are created at runtime (e.g. user names etc.). How can I build such objects using the GUICE infrastructure? Just commenting on the fields that I need to enter as @Inject does not work, as they don't seem to be set up when creating an object using the constructor. For instance:

 class C { @Inject private FactoryClass toBeInjected; private ConfigurationField passedIn; public C(ConfigurationField passedIn) { this.passedIn = passedIn; } } 

If my understanding is correct (and I could be wrong), the fact that I create a new instance of C through new , and not through Guice, means that the injection will not happen. I need to pass these parameters in the constructor, but also want some fields to be entered - so how can I solve this problem?

+6
source share
2 answers

A function specifically suited to “injection injection and passed parameters” will be “Assisted Injection” .

 class C { // Guice will automatically create an implementation of this interface. // This can be defined anywhere, but I like putting it in the class itself. interface Factory { C create(ConfigurationField passedIn); } @Inject private FactoryClass toBeInjected; private ConfigurationField passedIn; private SomeOtherDepIfYoudLike otherDep; @Inject public C(@Assisted ConfigurationField passedIn, SomeOtherDepIfYoudLike otherDep) { this.passedIn = passedIn; this.otherDep = otherDep; } } 

Now in your module:

 @Override public void configure() { install(new FactoryModuleBuilder().build(C.Factory.class)); } 

Now that someone wants to create C, they can avoid calling the constructor directly; instead, they inject C.Factory into which they pass the ConfigurationField instance of their choice and get a fully constructed, completely injected instance of C. (Like most well-designed DI objects, they can directly invoke the constructor.)

Please note that this design is especially useful in several ways:

  • You can use the constructor installation, treat all your fields as final, and treat the object as immutable.
  • If you make full use of the constructor installation, your object will never be in a partially initialized state, and your API will remain simple (call the constructor and your object is ready).
  • For testing, you can write any C.Factory implementation and return it to any instance. This may include test twins of C or its factory: fakes, scoffs or spies that you create manually or using Mockito, EasyMock, JMock, or any other mocking structure.
+2
source

What you are looking for is an “On Demand” Injection:

 public static void main(String[] args) { Injector injector = Guice.createInjector(...); CreditCardProcessor creditCardProcessor = new PayPalCreditCardProcessor(); injector.injectMembers(creditCardProcessor); } 

or for static things

 @Override public void configure() { requestStaticInjection(ProcessorFactory.class); ... } 

Everyone explained very well https://github.com/google/guice/wiki/Injections#on-demand-injection .

Note:

Both of these things are code smells and should really be used to port the old code to Guice. New code should not use these approaches.

+3
source

Source: https://habr.com/ru/post/987156/


All Articles