Reputation: 659
I have been learning about Guice. I see that there is an on-demand injection here.
I wanted to know what it is used for and some example. I have a scenario where I read a set of properties from a conf file. There is no injection there. Later on I want to inject the same instance of the config class I have from those properties to some other class.
class Props {
//set of properties read from a config file to this class
}
Props props = readProperties(); // instance of this class having all the properties but not put into injection container
Later in connection class I want to use its injection
@Inject
public Connection(Props props) {
this.props = props;
}
Is it possible to use on-demand injection of Guice in this case? Also I am using Play framework's conf file to load my module file. play.modules.enabled += com.example.mymodule
Upvotes: 2
Views: 1535
Reputation: 12021
If you want to use the very same configuration instance (of class Props) you could bind its instance as a singleton with a provider binding. This is of course not the only solution, but it makes sense for me.
Here is an example:
Define a provider:
public class PropsProvider implements Provider<Props>
{
@Override
public Props get()
{
...read and return Props here...
}
}
Use a provider binding in singleton scope:
bind(Props.class).toProvider(PropsProvider.class).in(Singleton.class);
Inject your configuration:
@Inject
public Connection(Props props) {
this.props = props;
}
You may read in the documentation:
Singletons are most useful for:
- stateful objects, such as configuration or counters
- objects that are expensive to construct or lookup
- objects that tie up resources, such as a database connection pool.
Maybe your configuration object matches the first and the second criteria. I would avoid reading the configuration from within the module. See why here.
I've used on-demand injection in a few unit test cases where I wanted to inject mock dependencies in the component under test and field injection was used (that's why I try to avoid field injections :-) ) AND I preferred not to use InjectMocks for certain reasons.
Here is a sample:
Component:
class SomeComponent
{
@Inject
Dependency dep;
void doWork()
{
//use dep here
}
}
The test itself:
@RunWith(MockitoJUnitRunner.class)
public class SomeComponentTest
{
@Mock
private Dependency mockDependency;
private SomeComponent componentToTest;
@Before
public void setUp() throws Exception
{
componentToTest = new SomeComponent();
Injector injector = Guice.createInjector(new AbstractNamingModule()
{
@Override
protected void configure()
{
bind(Dependency.class).toInstance(mockDependency);
}
});
injector.injectMembers(componentToTest);
}
@Test
public void test()
{
//test the component and/or proper interaction with the dependency
}
}
Upvotes: 3
Reputation: 11993
Load the properties in your module and them via bindConstant
Upvotes: 1