Reputation: 41
I have a small problem which I can't figure out to save my life.
Basically I need to register classes anytime dynamically using guice and then loop through them all.
Lets say this is my class to register Strategies but these strategies can be added anytime through the application running.
// Strategy registration may happen anytime, this is just an example
strategyManager.register(ExampleStrategy1.class);
strategyManager.register(ExampleStrategy2.class);
StrategyImpl class
public class StrategyImpl implements Strategy {
@Override
public void register(Class<? extends StrategyDispatcher> strat) {
//Add this class into provider or create an instance for it and add it into guice but how?
}
@Override
public void dispatchStrategy() {
//Find all strategies and execute them
}
}
I've tried using a Provider but have no idea how i'd add the registered class into the provider and retrieve them all?
@Override
protected void configure() {
bind(Strategy.class).toProvider(StrategyProvider.class);
}
My provider class always gets the same instance
public class StrategyProvider implements Provider<StrategyDispatcher> {
public LogManager get() {
return new StrategyDispatcherImpl();
}
}
The strategies that I add extend the StrategyDispatcherImpl class so i could cast them?
I need to add multiple binds to a same instance but it needs to be done dynamically and not using the bind method in configure but another way then be able to find all these strategies and execute them.
Upvotes: 2
Views: 195
Reputation: 14661
If you truly need it to happen at "any time" during the application life cycle then Guice then I think you will need some sort of Guice-aware Factory. I.e.
public class TestStuff {
@Test
public void testDynamicCreation() {
Injector injector = Guice.createInjector();
StrategyManager manager = injector.getInstance(StrategyManager.class);
Hello hello = injector.getInstance(Hello.class);
manager.doStuff();
assertThat(hello.helloCalled, is(false));
manager.register(Hello.class); // DYNAMIC!!
manager.doStuff();
assertThat(hello.helloCalled, is(true));
}
}
interface Strategy {
void doStuff();
}
@Singleton
class Hello implements Strategy {
boolean helloCalled = false;
public void doStuff() {
helloCalled = true;
}
}
class StrategyManager {
private final Collection<Strategy> strategies = new ArrayList<>();
private final StrategyFactory factory;
@Inject
StrategyManager(StrategyFactory factory) {
this.factory = factory;
}
public void register(Class<? extends Strategy> strat) {
strategies.add(factory.create(strat));
}
public void doStuff() {
for (Strategy s : strategies) {
s.doStuff();
}
}
}
class StrategyFactory {
private final Injector injector;
@Inject
StrategyFactory(Injector injector) {
this.injector = injector;
}
public Strategy create(Class<? extends Strategy> clazz) {
return injector.getInstance(clazz);
}
}
If it is not "dynamic" after the initialization phase then you are after the "multibinder" I think.
Upvotes: 2