guice 3.0 の AssistedInject 新機能

Google guice 3.0 がリリースされて新機能の1つに、AssistedInject の Factory生成がある。

guice 2.0 では、
 bind(PaymentFactory.class).toProvider(FactoryProvider.newFactory(
    PaymentFactory.class, RealPayment.class));
toProvider でFactoryProvider.newFactory の結果を指定したりしていた。

guice 3.0 では、
configure()の中で記述する install に渡す Module を
com.google.inject.assistedinject.FactoryModuleBuilder の buildメソッド
生成する。


以下のサンプルのように、Factory のインターフェースだけでその実装クラスを記述しないで
済むことと、
下記サンプルのように、Factory インターフェースのメソッドアノテーション
別々のクラスのインスタンスを生成できることが多くの可能性を期待できる。
(下記→ AnnotatedCarFactory)

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.name.Names;
  :
Injector injector = Guice.createInjector(new AbstractModule(){
   @Override
   protected void configure(){
      binder().bind(String.class).toInstance("Test body!");
      install(new FactoryModuleBuilder().build(AllCarFactory.class));
   }
});
AllCarFactory allfactory = injector.getInstance(AllCarFactory.class);
Mustang mustang = allfactory.getMustang("RED");
Beetle beetle = allfactory.getBeetle("GREEN");

System.out.println(mustang.getClass().getName()+"\t"+mustang.color()+"\t body = "+mustang.body());
System.out.println(beetle.getClass().getName()+"\t"+beetle.color()+"\t body = "+beetle.body());

Injector injector2 = Guice.createInjector(new AbstractModule(){
   @Override
   protected void configure(){
      binder().bind(String.class).toInstance("Test body!");
      install(new FactoryModuleBuilder()
               .implement(Car.class,Names.named("America"),Mustang.class)
               .implement(Car.class,Names.named("German"),Beetle.class)

               .build(AnnotatedCarFactory.class));
   }
});
AnnotatedCarFactory anofactory = injector2.getInstance(AnnotatedCarFactory.class);
Car mustang2 = anofactory.getAmericanCar("RED");
Car beetle2 = anofactory.getGermanCar("GREEN");

System.out.println(mustang2.getClass().getName()+"\t"+mustang2.color()+"\t body = "+mustang2.body());
System.out.println(beetle2.getClass().getName()+"\t"+beetle2.color()+"\t body = "+beetle2.body());

------------------------------------
public interface AllCarFactory{
   public Mustang getMustang(String color);
   public Beetle  getBeetle(String color);
}

------------------------------------
import javax.inject.Named;
public interface AnnotatedCarFactory{
   @Named("America") public Car getAmericanCar(String color);
   @Named("German")  public Car getGermanCar(String color);
}
------------------------------------
public interface Car{
   public String color();
   public String body();
}
------------------------------------
package test.factorymodulebuild;

import javax.inject.Inject;
import com.google.inject.assistedinject.Assisted;

public class Mustang implements Car{
   private String color;
   private String body;
   @Inject
   public Mustang(@Assisted String color,String body){
      this.color = color;
      this.body = body;
   }
   @Override
   public String color(){
      return this.color;
   }

   @Override
   public String body(){
      return this.body;
   }
}
------------------------------------
package test.factorymodulebuild;

import javax.inject.Inject;
import com.google.inject.assistedinject.Assisted;

public class Beetle implements Car{
   private String color;
   private String body;
   @Inject
   public Beetle(@Assisted String color,String body){
      this.color = color;
      this.body = body;
   }
   @Override
   public String color(){
      return this.color;
   }
   @Override
   public String body(){
      return this.body;
   }
}
------------------------------------
実行結果は、、、
test.factorymodulebuild.Mustang  RED     body = Test body!
test.factorymodulebuild.Beetle   GREEN   body = Test body!
test.factorymodulebuild.Mustang  RED     body = Test body!
test.factorymodulebuild.Beetle   GREEN   body = Test body!
------------------------------------

JSR-330 サポートにより、com.google.inject.name.Named ではなく、
javax.inject.Named の使用でOKなのもここで証明されuた