Spring学習資料―注入に依存する(三)
1.3より多くの話題
1.3.1インターフェース多実現
一つのインターフェースが複数実現すれば、@InjectとModuleを通じて直接実現するのは難しいですが、このような現象は確かに存在します.そこで、Guiceは他の注入方式を提供してこの問題を解決します.例えば以下のカスタムコメントです.
この構造についてもいくつかの質問をします.
問題(1)静的に複数のサービスを注入するにはどう書きますか?
実は、教程02を参考にして、次の例を使ってもいいです.
残念ですが、似たようなエラーがあります.つまり、複数のサービスを結びつけることはできません.
プログラマは怠け者です.そこでGoogleはNamesのテンプレートを提供して注釈を作成してくれました.次の例を見てください.
1.3.2 Provider注入
教程第一篇では、Providerを通してサービスを注入できることについて言及しました.
まず私たちはProviderを作って出てきます.
注入の過程は下のコードを見てください.
もちろん自動的にサービスを注入したいなら、@ProviderBy注を使ってもいいです.
1.3バインディング定数
以下の例を見て,結合整数値の例を示した.
binder.bind(int.class).annotatedWith(Names.named(「v」)).toInstance(12);
接続int以外にも、コンスタントBindingBuiderクラスで他の基本タイプをバインドすることができます.
基本タイプ以外にも、ProptiesをGuiceに結びつけることができます.もちろん、Proptiesは本質的にはMapであるため、GuiceもMapを一つ縛ることができます.
1.3.1インターフェース多実現
一つのインターフェースが複数実現すれば、@InjectとModuleを通じて直接実現するのは難しいですが、このような現象は確かに存在します.そこで、Guiceは他の注入方式を提供してこの問題を解決します.例えば以下のカスタムコメントです.
1 public interface Service {
2
3 void execute();
4 }
5
6
1 public class HomeService implements Service {
2 @Override
3 public void execute() {
4 System.out.println("home.imxylz.cn");
5 }
6 }
1 public class WwwService implements Service {
2 @Override
3 public void execute() {
4 System.out.println("www.teny32.blog.51cto.com");
5 }
6 }
1 @Retention(RetentionPolicy.RUNTIME)
2 @Target({FIELD,PARAMETER})
3 @BindingAnnotation
4 public @interface Home {
5 }
1 @Retention(RetentionPolicy.RUNTIME)
2 @Target({FIELD,PARAMETER})
3 @BindingAnnotation
4 public @interface Www {
5 }
上のコードは一つのサービスです.WwServiceとHomeServiceの二つの実装があります.同時にWwwとHomeの二つの注釈があります.はい、次は私たちの主役をお願いします.1 /**
2 * $Id: MultiInterfaceServiceDemo.java
3 * Teny study project (www.teny32.blog.51cto.com)
4 */
5 package cn.imxylz.study.guice.inject.more;
6
7 import com.google.inject.Binder;
8 import com.google.inject.Guice;
9 import com.google.inject.Inject;
10 import com.google.inject.Module;
11
12 /** a demo with multi interfaces
13 * @author
14 * @version 1.0
15 */
16 public class MultiInterfaceServiceDemo {
17 @Inject
18 @Www
19 private Service wwwService;
20 @Inject
21 @Home
22 private Service homeService;
23 public static void main(String[] args) {
24 MultiInterfaceServiceDemo misd = Guice.createInjector(new Module() {
25 @Override
26 public void configure(Binder binder) {
27 binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
28 binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class);
29 }
30 }).getInstance(MultiInterfaceServiceDemo.class);
31 misd.homeService.execute();
32 misd.wwwService.execute();
33 }
34 }
35
36
このような構造は2つのサービスを注入するもので、wServiceは@Www注解関連のWwwServiceサービスであり、homeServiceは@Home注解関連のHomeServiceサービスである.この構造についてもいくつかの質問をします.
問題(1)静的に複数のサービスを注入するにはどう書きますか?
実は、教程02を参考にして、次の例を使ってもいいです.
1 public class StaticMultiInterfaceServiceDemo {
2 @Inject
3 @Www
4 private static Service wwwService;
5 @Inject
6 @Home
7 private static Service homeService;
8 public static void main(String[] args) {
9 Guice.createInjector(new Module() {
10 @Override
11 public void configure(Binder binder) {
12 binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
13 binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class);
14 binder.requestStaticInjection(StaticMultiInterfaceServiceDemo.class);
15 }
16 });
17 StaticMultiInterfaceServiceDemo.homeService.execute();
18 StaticMultiInterfaceServiceDemo.wwwService.execute();
19 }
20 }
問題(2):もし一つの属性が複数のインターフェースをバインドしてしまったら、どうすればいいですか?残念ですが、似たようなエラーがあります.つまり、複数のサービスを結びつけることはできません.
1) cn.imxylz.study.guice.inject.more.StaticMultiInterfaceServiceDemo.wwwService has more than one annotation annotated with @BindingAnnotation: cn.imxylz.study.guice.inject.more.Www and cn.imxylz.study.guice.inject.more.Home
at cn.imxylz.study.guice.inject.more.StaticMultiInterfaceServiceDemo.wwwService(StaticMultiInterfaceServiceDemo.java:17)
問題(3):私は怠け者です.注釈を書いて、複数のサービスを区別したいです.どうすればいいですか?プログラマは怠け者です.そこでGoogleはNamesのテンプレートを提供して注釈を作成してくれました.次の例を見てください.
1 public class NoAnnotationMultiInterfaceServiceDemo {
2 @Inject
3 @Named("Www")
4 private static Service wwwService;
5 @Inject
6 @Named("Home")
7 private static Service homeService;
8 public static void main(String[] args) {
9 Guice.createInjector(new Module() {
10 @Override
11 public void configure(Binder binder) {
12 binder.bind(Service.class).annotatedWith(Names.named("Www")).to(WwwService.class);
13 binder.bind(Service.class).annotatedWith(Names.named("Home")).to(HomeService.class);
14 binder.requestStaticInjection(NoAnnotationMultiInterfaceServiceDemo.class);
15 }
16 });
17 NoAnnotationMultiInterfaceServiceDemo.homeService.execute();
18 NoAnnotationMultiInterfaceServiceDemo.wwwService.execute();
19 }
20 }
上記の例では、私たちはNamedを使って、私たちのサービスはどのような注釈を使うべきかを表示しています.もちろん前提は、対応するサービスを注釈と関連させています.1.3.2 Provider注入
教程第一篇では、Providerを通してサービスを注入できることについて言及しました.
まず私たちはProvider
1 public class WwwServiceProvider implements Provider<Service> {
2
3 @Override
4 public Service get() {
5 return new WwwService();
6 }
7 }
8
9
上のProviderの意味は簡単で、毎回新しいWwwServiceの対象ができます.注入の過程は下のコードを見てください.
1 public class ProviderServiceDemo {
2
3 @Inject
4 private Service service;
5
6 public static void main(String[] args) {
7 Injector inj= Guice.createInjector(new Module() {
8 @Override
9 public void configure(Binder binder) {
10 binder.bind(Service.class).toProvider(WwwServiceProvider.class);
11 }
12 });
13 ProviderServiceDemo psd = inj.getInstance(ProviderServiceDemo.class);
14 psd.service.execute();
15 }
16
17 }
18
19
これは明らかにスレッドと結合すればとてもいいです.例えば、ThreadLocalを使ってスレッドのオブジェクト交換ができます.もちろん自動的にサービスを注入したいなら、@ProviderBy注を使ってもいいです.
1 @ProvidedBy(WwwServiceProvider.class)
2 public interface Service {
3
4 void execute();
5 }
6
7
これでModuleを使ってサービスをServiceにProviderを結びつける必要がなくなります.サービスを受けるのは簡単です.ProviderServiceDemo psd = Guice.createInjector().getInstance(ProviderServiceDemo.class);
psd.service.execute();
上記の2つの方法以外にも、プロバイダーを注入することができます.例えば、次の例では、属性はServiceではなく、プロバイダー<Service>です.1 public class ProviderServiceDemo {
2
3 @Inject
4 private Provider<Service> provider;
5
6 public static void main(String[] args) {
7 ProviderServiceDemo psd = Guice.createInjector(new Module() {
8 @Override
9 public void configure(Binder binder) {
10 binder.bind(Service.class).toProvider(WwwServiceProvider.class);
11 }
12 }).getInstance(ProviderServiceDemo.class);
13 psd.provider.get().execute();
14 }
15 }
16
17
もちろんです.WwwServiceProviderは毎回新しいサービスを構築していますので、Provider ServiceDemoの中のプロバイダーは毎回獲得するサービスも違います.1.3バインディング定数
以下の例を見て,結合整数値の例を示した.
1 public class ConstantInjectDemo {
2
3 @Inject
4 @Named("v")
5 private int v;
6 public static void main(String[] args) {
7
8 ConstantInjectDemo cid = Guice.createInjector(new Module() {
9 @Override
10 public void configure(Binder binder) {
11 binder.bindConstant().annotatedWith(Names.named("v")).to(12);
12 }
13 }).getInstance(ConstantInjectDemo.class);
14 System.out.println(cid.v);
15 }
16 }
17
18
もちろん、Namedを使ってもいいです.自分で注釈を書いてもいいです.しかし、あまり効果がなさそうです.上記以外にも、以下のように実現できます.binder.bind(int.class).annotatedWith(Names.named(「v」)).toInstance(12);
接続int以外にも、コンスタントBindingBuiderクラスで他の基本タイプをバインドすることができます.
com.google.inject.binder.ConstantBindingBuilder.to(String)
com.google.inject.binder.ConstantBindingBuilder.to(long)
com.google.inject.binder.ConstantBindingBuilder.to(boolean)
com.google.inject.binder.ConstantBindingBuilder.to(double)
com.google.inject.binder.ConstantBindingBuilder.to(float)
com.google.inject.binder.ConstantBindingBuilder.to(short)
com.google.inject.binder.ConstantBindingBuilder.to(char)
1.3.4バインディングPropties基本タイプ以外にも、ProptiesをGuiceに結びつけることができます.もちろん、Proptiesは本質的にはMap
1 @Inject
2 @Named("web")
3 private String web;
4
5 public static void main(String[] args) {
6
7 ConstantInjectDemo cid = Guice.createInjector(new Module() {
8 @Override
9 public void configure(Binder binder) {
10 Properties properties= new Properties();
11 properties.setProperty("web", "www.teny32.blog.51cto.com");
12 Names.bindProperties(binder, properties);
13 }
14 }).getInstance(ConstantInjectDemo.class);
15 System.out.println(cid.web);
16 }
17
18
51CTO !http://teny32.blog.51cto.com/ !