vipx / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Allow for scope aliases #687

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Let's say I have a:

bindScope(MyScoped.class, new MyScope());

I wish to be able to:

bindScope(MyOtherScoped.class, MyScoped.class);

*****************************************************

Currently, there are a few ways to accomplish something like that (which I list 
drawbacks here):

1. local var

{
  MyScope myScope = new MyScope();
  bindScope(MyScoped.class, myScope);
  bindScope(MyOtherScoped.class, myScope);
}

Perfect, except this limits things to when both bindScopes are in the same 
method, which is mostly useless.

2. global static

public static final MyScope MY_SCOPE = new MyScope();

{
  bindScope(MyScoped.class, MY_SCOPE);
}

{
  bindScope(MyOtherScoped.class, MY_SCOPE);
}

This is problematic for Modules.override, and it is also not possible if 
MyScope is not stateless, and I wish to create multiple injectors in the same 
JVM. It's also a problem if MyScope's constructor takes a param (not known at 
static init time).

3. create new instances

{
  bindScope(MyScoped.class, new MyScope());
}

{
  bindScope(MyOtherScoped.class, new MyScope());
}

This is the least problematic one, but it's still inconvenient, particularly if 
MyScope takes a constructor param that should be shared. It also feels wrong to 
require multiple instances of the Scope to be created, when all I really wanted 
was one per injector.

4. Store it in the Module where it's created

class MyModuleA extends AbstractModule {

public final MyScope myScope = new MyScope();

public void configure () {
  bindScope(MyScoped.class, myScope);
}

class MyModuleB extends AbstractModule {

public void configure () {
  MyModuleA a = new MyModuleA();
  install(a);
  bindScope(MyOtherScoped.class, a.myScope);
}

This, though, makes it not possible to install MyModuleA multiple times (see 
http://code.google.com/p/guiceberry/issues/detail?id=21).

*****************************************************

The ideal place to create a scope instance is in a "configure" method. If only 
I could create aliases to a defined scope annotation as needed, things would be 
a lot easier.

Original issue reported on code.google.com by zorze...@gmail.com on 27 Feb 2012 at 5:10

GoogleCodeExporter commented 9 years ago
FYI, it is possible to do this today (although somewhat annoying) using the 
Guice SPI.

untested code:
 Module aliasScopeModule(
    Class<? extends Annotation> originalScope,
    Class<? extends Annotation> aliasScope,
    Module srcModule) {
   List<Element> elements = Elements.getElements(srcModule);
   for (Element element : elements) {
     Scope scope = element.acceptVisitor(new DefaultElementVisitor<Scope>()) {
       public Scope visit(ScopeBinding binding) {
         if (binding.getAnnotationType() == originalScope) {
           return binding.getScope();
         }
       }
     });
     if (scope != null) {
       return new AbstractModule() [
         public void configure() {
           bindScope(aliasScope, scope);
         }
       };
     }
   }
   throw new IllegalStateException("scope: " + originalScope + " not found in module.");
 }

usage:
  Module m = new MyAppModule();
  Module scopeAlias = aliasScopeModule(OriginalScopeAnnotation.class, AliasAnnotation.class, m);
  MyApp app = Guice.createInjector(m, scopeAlias).getInstance(MyApp.class);

Original comment by sberlin on 27 Feb 2012 at 5:40