Spring学習資料の依存注入(一)


1.依存注入
1.1類依存注入
バインディングとは、1つのインターフェースを特定のクラスに結びつけることで、クライアントは具体的な実装に関心を持たず、対応するインターフェースを取得してサービスを完了するだけでよい.
HelloWorld.java
1     public interface HelloWorld {
2
3         String sayHello();
4     }
5
そして具体的な実現です.ハローワールドImpl.java
1     public class HelloWorldImpl implements HelloWorld {
2
3         @Override
4         public String sayHello() {
5             return "Hello, world!";
6         }
7     }
8
テストの例を書いてみてください.Helle World Test.java
1     public class HelleWorldTest {
 2
 3         @Test
 4         public void testSayHello() {
 5           Injector inj=  Guice.createInjector(new Module() {
 6                 @Override
 7                 public void configure(Binder binder) {
 8                     binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
 9                 }
10             });
11           HelloWorld hw = inj.getInstance(HelloWorld.class);
12           Assert.assertEquals(hw.sayHello(), "Hello, world!");
13         }
14     }
15
この例は非常に簡単で、簡単にハローワールドの例をハローワールドに関連付けることになります.Guiceがハローワールドの例を取得したい時、Guiceはハローワールドの実例を返します.それから、ハロルドサービスを呼び出す方法ができます.
問題(1)ハロルドは一例ですか?テストします
1 HelloWorld hw = inj.getInstance(HelloWorld.class);
2 Assert.assertEquals(hw.sayHello(), "Hello, world!");
3 HelloWorld hw2 = inj.getInstance(HelloWorld.class);
4 System.out.println(hw.hashCode()+"->"+hw2.hashCode());
5 Assert.assertEquals(hw.hashCode(), hw2.hashCode());
答え(1)テストの結果、ハロルドは単一の例ではなく、毎回新しいインスタンスを返すと教えてくれました.
問題(2)ハロルドの例はハローワールドですか?強制的にモデルチェンジできますか?
HelloWorld hw = inj.getInstance(HelloWorld.class);
System.out.println(hw.getClass().getName());
答え(2)はcn.imxylz.study.guce.hello world.Hello World Implを出力しました.見たところ確かに正常な例に戻りました.あまり多くの変換と代理はしていません.
問題(3)、もし複数のバインディングが同じインターフェースに実現されれば、どのような状況が発生しますか?
1 public class HelloWorldImplAgain implements HelloWorld {
2     @Override
3     public String sayHello() {
4         return "Hello world again.";
5     }
6 }
binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
binder.bind(HelloWorld.class).to(HelloWorldImplAgain.class);
残念ながら、Guiceは現在、複数のインスタンスを同じインターフェースに結びつけることができないようです.
com.google.inject.CreationException: Guice creation errors:
1) A binding to cn.imxylz.study.guice.helloworld.HelloWorld was already configured at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28).
  at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:29)
問題(4)は、実現クラスと結合してもいいですか?
1 Injector inj=  Guice.createInjector(new Module() {
2       @Override
3       public void configure(Binder binder) {
4           binder.bind(HelloWorldImpl.class).to(HelloWorldImpl.class);
5       }
6   });
7 HelloWorld hw = inj.getInstance(HelloWorldImpl.class);
8 System.out.println(hw.sayHello());
とても不幸です.自分で自分を縛ってはいけません.
1) Binding points to itself.
  at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28)
私たちはビッドの文法を見に来ました.
<T> AnnotatedBindingBuilder<T> bind(Class<T> type);
ScopedBindingBuilder to(Class<? extends T> implementation);
つまり、一つの種類のサブクラスだけを自分自身に結びつけることができるということです.改造して,サブクラスに切り替える.
1     public class HelloWorldSubImpl extends HelloWorldImpl {
2
3         @Override
4         public String sayHello() {
5             return "@HelloWorldSubImpl";
6         }
7     }
8
1 Injector inj=  Guice.createInjector(new Module() {
2             @Override
3             public void configure(Binder binder) {
4                 binder.bind(HelloWorldImpl.class).to(HelloWorldSubImpl.class);
5             }
6         });
7       HelloWorldImpl hw = inj.getInstance(HelloWorldImpl.class);
8       System.out.println(hw.sayHello());
よかったです.サブバインディングをサポートしています.このように実現クラスをリリースしても、私たちは後期に実現クラスを交替する方法があります.
bindを使うと利点があります.JAVA 5以上の泛型はコンパイラで確定しますので、バインディングエラーを検出してもらえます.これは配置ファイルでは検出できません.
このようにModuleはMapのように見えますが、KeyによってValueを取得すると、非常に単純な論理です.
問題(5)は、私たちが自分で作った実例に結び付けられますか?
もちろんいいです.次の例を見てください.
1 Injector inj=  Guice.createInjector(new Module() {
2             @Override
3             public void configure(Binder binder) {
4                 binder.bind(HelloWorld.class).toInstance(new HelloWorldImpl());
5             }
6         });
7       HelloWorld hw = inj.getInstance(HelloWorld.class);
8       System.out.println(hw.sayHello());
問題(6)は、自分で論理的に相手を構成したくないですが、いいですか?
答え(6)は、Guiceがオブジェクトを構成する方式を提供してくれます.
1 Injector inj=  Guice.createInjector(new Module() {
 2       @Override
 3       public void configure(Binder binder) {
 4           binder.bind(HelloWorld.class).toProvider(new Provider<HelloWorld>() {
 5               @Override
 6               public HelloWorld get() {
 7                   return new HelloWorldImpl();
 8               }
 9           });
10       }
11   });
12 HelloWorld hw = inj.getInstance(HelloWorld.class);
13 System.out.println(hw.sayHello());
問題(7)、実現類はバインディングなしで取得できますか?例えば、ハローワールドの例を取りたいですが、Moduleバインディングを通じてではないですか?
答え(7)は、いいです.実际には、Guiceは自动的に実现クラスを探すことができます.
Injector inj=  Guice.createInjector();
HelloWorld hw = inj.getInstance(HelloWorldImpl.class);
System.out.println(hw.sayHello());
問題(8)は注解で注入が完了しますか?マニュアル関連の実現類を望まない.
答え(8)、はい、Guiceは注釈を提供した方式で関連を完成します.私たちはこのインターフェースがどのようなインプリメンテーションに関連しているかをインターフェースで明示しなければなりません.
1     @ImplementedBy(HelloWorldImpl.class)
2     public interface HelloWorld {
3
4         String sayHello();
5     }
6
Injector inj=  Guice.createInjector();
HelloWorld hw = inj.getInstance(HelloWorld.class);
System.out.println(hw.sayHello());
実際には、注釈されたインターフェースについては、まだModuleを使用して関連付けることができます.このようにして取得された例は、@ImplementdBy注釈関連の実例ではなくModule関連の例となります.このように依然として一つの原則に従い、手動は自動より優れている.
問題(9)を振り返ってみます.(1)どのように一つの例を結びつけますか?
1     Injector inj = Guice.createInjector(new Module() {
 2
 3         @Override
 4         public void configure(Binder binder) {
 5             binder.bind(HelloWorld.class).to(HelloWorldImplAgain.class).in(Scopes.SINGLETON);
 6         }
 7     });
 8     HelloWorld hw = inj.getInstance(HelloWorld.class);
 9     HelloWorld hw2 = inj.getInstance(HelloWorld.class);
10     System.out.println(hw.hashCode() + "->" + hw2.hashCode());
11
現在取得された例は単一の例であり、要求毎に新たなインスタンスを生成しないことが見られる.実はGuiceは二つのScopeを提供しています.comple.google.inject.Scompes.SINGLETONとcomp.google.inject.Scoopes.NOSCOPEとは、scopeがないということは、新しいインスタンスを毎回生成することである.
自動注入は非常に簡単です.Singleton注釈を達成するためには、クラスに加えるだけでいいです.
1     @Singleton
2     public class HelloWorldImpl implements HelloWorld {
3
4         @Override
5         public String sayHello() {
6             return "Hello, world!";
7         }
8     }
9