Guiceのスコープが不勉強であったため、少しメモ
以下git sample
https://github.com/KOBUO/sample-guice
Project.Tree
└─src
├─main
│ ├─java
│ │ └─sample
│ │ └─guice
│ │ │ Main.java
│ │ │
│ │ └─subpackage
│ │ │ SampleExecutor.java
│ │ │ SampleFactory.java
│ │ │
│ │ ├─singleton
│ │ │ Hello.java
│ │ │
│ │ └─test
│ │ │ ITester.java
│ │ │ Test.java
│ │ │
│ │ └─impl
│ │ Sample1Tester.java
│ │ Sample2Tester.java
│ │ Sample3Tester.java
Mainで親injectorを生成
Hello(Singleton)をbind
Main.java
package sample.guice;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import sample.guice.subpackage.SampleExecutor;
import sample.guice.subpackage.singleton.Hello;
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
this.bind(Hello.class).toInstance(new Hello("World")); //①
}
});
injector.getInstance(SampleExecutor.class).execute();
System.exit(0);
}
}
SampleFactoryで親injectorをコンストラクタinject
Injector#createChildInjectorで子injectorを生成
SampleFactory.java
package sample.guice.subpackage;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector;
import sample.guice.subpackage.test.ITester;
import sample.guice.subpackage.test.Test;
import sample.guice.subpackage.test.impl.Sample1Tester;
import sample.guice.subpackage.test.impl.Sample2Tester;
import sample.guice.subpackage.test.impl.Sample3Tester;
public class SampleFactory {
private final Injector _injector;
@Inject
public SampleFactory(Injector injector) {
this._injector = injector;
}
ITester getTester(Test test) {
Injector injector = this._injector.createChildInjector(new AbstractModule() {
@Override
protected void configure() {
bind(Hello.class).toInstance(new Hello("SubWorld")); //②
}
});
switch (test) {
case SAMPLE1:
return injector.getInstance(Sample1Tester.class);
case SAMPLE2:
return injector.getInstance(Sample2Tester.class);
case SAMPLE3:
return injector.getInstance(Sample3Tester.class);
default:
throw new IllegalArgumentException();
}
}
}
HelloでSingletonアノテーションを付与
Hello.java
package sample.guice.subpackage.singleton;
import javax.inject.Singleton;
@Singleton
public class Hello {
private final String _name;
public Hello(String name){
System.out.println("constructor is Hello");
this._name = name;
}
public void message(){
System.out.println(String.format("Hello %s", this._name));
}
}
実行すると以下のメッセージが。
HelloのインスタンスはMainでもう生成している旨出力
親injectorが子に受け継がれていることがわかる
Terminal.log
Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:
1) A binding to sample.guice.subpackage.singleton.Hello was already configured at sample.guice.Main$1.configure(Main.java:14).
at sample.guice.subpackage.SampleFactory$1.configure(SampleFactory.java:27)
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:543)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:159)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
at com.google.inject.internal.InjectorImpl.createChildInjector(InjectorImpl.java:237)
at com.google.inject.internal.InjectorImpl.createChildInjector(InjectorImpl.java:242)
at sample.guice.subpackage.SampleFactory.getTester(SampleFactory.java:24)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at sample.guice.subpackage.SampleExecutor.execute(SampleExecutor.java:19)
at sample.guice.Main.main(Main.java:17)
Mainのbind(Hello)をコメントアウトすると
子のスコープでシングルトンであるため、3回コンストラクタが呼ばれる。
Terminal.log
> Task :Main.main()
constructor is Hello
Hello SubWorld
constructor is Hello
Hello SubWorld
constructor is Hello
Hello SubWorld
SampleFactoryのbind(Hello)をコメントアウトすると
親のスコープでシングルトンであるため、1回コンストラクタが呼ばれる。
> Task :Main.main()
constructor is Hello
Hello World
Hello World
Hello World