LoginSignup
1
0

More than 3 years have passed since last update.

Guiceの親子Injectorについてメモ自分用

Posted at

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
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0