Created
July 7, 2014 17:53
-
-
Save gissuebot/efae9ea404120ea81de4 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 38, comment 19
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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