Skip to content

Instantly share code, notes, and snippets.

@gissuebot
Created July 7, 2014 17:53
Show Gist options
  • Save gissuebot/efae9ea404120ea81de4 to your computer and use it in GitHub Desktop.
Save gissuebot/efae9ea404120ea81de4 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 38, comment 19
import com.google.inject.*;
import com.google.inject.internal.Sets;
import com.google.inject.internal.Preconditions;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.TypeListener;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.InjectionListener;
import java.util.HashSet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Makes @Eager work.
*/
public class EagerAbstractModule extends AbstractModule {
protected void configure() {
LazyListener listener = new LazyListener();
requestInjection(listener);
bindListener(Matchers.any(), listener);
}
@Retention(RetentionPolicy.RUNTIME)
public @interface Eager {
}
private static class LazyListener implements TypeListener {
private HashSet<TypeLiteral<?>> foundEager = Sets.newHashSet();
private Injector injector;
@Inject
// we are guaranteed that this method will be called after injector creation
public void afterInjectorCreated(Injector injector, Stage stage) {
this.injector = injector;
// eagerly initialize everything by getting an instance
for (TypeLiteral<?> typeLiteral : foundEager) {
injector.getInstance(Key.get(typeLiteral));
}
foundEager.clear();
// some heavy lifting create a new child injector but it has AOP on the
}
public <I> void hear(final TypeLiteral<I> literal, TypeEncounter<I> encounter) {
// is the class eager?
if (isEager(literal.getRawType())) {
if (injector == null) {
// injector not yet crated
foundEager.add(literal);
} else {
// this is a JIT request after injector is created
// getInstance will get eagerly created in any case
// getProvider s another story since only the provider for eager singleton will get created
// and not the eager singleton aswell
// we could handle this case with heard method if it existed
}
}
}
private boolean isEager(Class<?> type) {
// is annotated
return type.isAnnotationPresent(Eager.class);
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new EagerAbstractModule() {
@Override
protected void configure() {
// very ugly to have to call super
super.configure();
bind(AEager.class);
bind(A.class);
bind(I.class).to(IImpl.class);
}
});
Injector childInjector = injector.createChildInjector(new EagerAbstractModule() {
protected void configure() {
super.configure();
bind(BEager.class);
bind(B.class);
}
});
Provider<P> pProvider = childInjector.getProvider(P.class);
Preconditions.checkState(AEager.instanceCount == 1);
Preconditions.checkState(BEager.instanceCount == 1);
Preconditions.checkState(A.instanceCount == 0);
Preconditions.checkState(B.instanceCount == 0);
// linked bindings work
Preconditions.checkState(IImpl.instanceCount == 1);
// toProvider (: if have heard method on listener it could be done
Preconditions.checkState(P.instanceCount == 1);
}
@Singleton
@Eager
public static class AEager {
static int instanceCount = 0;
int instanceId = instanceCount++;
}
@Singleton
@Eager
public static class BEager {
static int instanceCount = 0;
int instanceId = instanceCount++;
}
@Singleton
public static class A {
static int instanceCount = 0;
int instanceId = instanceCount++;
}
@Singleton
public static class B {
static int instanceCount = 0;
int instanceId = instanceCount++;
}
@Singleton
@Eager
public static class P {
static int instanceCount = 0;
int instanceId = instanceCount++;
}
public interface I{
}
@Singleton
@Eager
public static class IImpl implements I{
static int instanceCount = 0;
int instanceId = instanceCount++;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment