Guice依賴注入(接口多實現)

本教程主要詳細講解Guice依賴注入中的特性接口多實現,一般使用到guice的框架的插件機制都是基於該方式實現。

基礎環境


技術 版本
Java 1.8+
Guice 4.2.3

初始化項目


  • 初始化項目

  
  
  
  1. mvn archetype:generate -DgroupId=com.edurt.sli.guice -DartifactId=guice-binder-multiple -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=1.0.0 -DinteractiveMode=false

  • 修改pom.xml增加Guice依賴

  
  
  
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <project xmlns="http://maven.apache.org/POM/4.0.0"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">


  5. <parent>

  6. <artifactId>learn-integration-guice</artifactId>

  7. <groupId>com.edurt.sli.guice</groupId>

  8. <version>1.0.0</version>

  9. </parent>


  10. <modelVersion>4.0.0</modelVersion>


  11. <artifactId>guice-binder-multiple</artifactId>

  12. <name>Guice依賴注入(接口多實現)</name>


  13. <properties>

  14. <system.java.version>1.8</system.java.version>

  15. <guice.version>4.2.3</guice.version>

  16. <lombok.version>1.18.2</lombok.version>

  17. </properties>


  18. <dependencies>

  19. <dependency>

  20. <groupId>com.google.inject</groupId>

  21. <artifactId>guice</artifactId>

  22. <version>${guice.version}</version>

  23. </dependency>

  24. <dependency>

  25. <groupId>org.projectlombok</groupId>

  26. <artifactId>lombok</artifactId>

  27. <version>${lombok.version}</version>

  28. </dependency>

  29. </dependencies>


  30. <build>

  31. <plugins>

  32. <plugin>

  33. <groupId>org.apache.maven.plugins</groupId>

  34. <artifactId>maven-compiler-plugin</artifactId>

  35. <version>${plugin.maven.compiler.version}</version>

  36. <configuration>

  37. <source>${system.java.version}</source>

  38. <target>${system.java.version}</target>

  39. </configuration>

  40. </plugin>

  41. </plugins>

  42. </build>


  43. </project>

guice: guice就是我們核心要使用的依賴

接口多實現注入


如果一個接口有多個實現,如果單單通過 @InjectModule都難以直接實現,但多實現是經常會出現的,Guice提供了其它注入方式來解決此問題。

  • 創建 com.edurt.sli.guice.multiple文件夾,並在該文件夾下創建 Service接口文件,用於添加我們需要測試的函數

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. public interface Service {


  3. void print(String source);


  4. }

  • 創建 Service接口的實現類 JavaService和 GuiceService,用於實現接口中的方法,代碼如下

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. public class JavaService implements Service {


  3. @Override

  4. public void print(String source) {

  5. System.out.println("Java Service " + source);

  6. }


  7. }

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. public class GuiceService implements Service {


  3. @Override

  4. public void print(String source) {

  5. System.out.println("Guice Service " + source);

  6. }


  7. }

  • 創建 Guice和 Java註解類,用於提供guice框架標識

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. import com.google.inject.BindingAnnotation;


  3. import java.lang.annotation.ElementType;

  4. import java.lang.annotation.Retention;

  5. import java.lang.annotation.RetentionPolicy;

  6. import java.lang.annotation.Target;


  7. @Retention(RetentionPolicy.RUNTIME)

  8. @Target({ElementType.FIELD, ElementType.PARAMETER})

  9. @BindingAnnotation

  10. public @interface Guice {

  11. }

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. import com.google.inject.BindingAnnotation;


  3. import java.lang.annotation.ElementType;

  4. import java.lang.annotation.Retention;

  5. import java.lang.annotation.RetentionPolicy;

  6. import java.lang.annotation.Target;


  7. @Retention(RetentionPolicy.RUNTIME)

  8. @Target({ElementType.FIELD, ElementType.PARAMETER})

  9. @BindingAnnotation

  10. public @interface Java {

  11. }

  • 創建用於測試注入的應用類 Application,代碼如下

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. import com.google.inject.Guice;

  3. import com.google.inject.Inject;


  4. public class Application {


  5. @Inject

  6. @Java

  7. public Service java;


  8. @Inject

  9. @com.edurt.sli.guice.multiple.Guice

  10. public Service guice;


  11. public static void main(String[] args) {

  12. Application application = Guice.createInjector(binder -> {

  13. binder.bind(Service.class).annotatedWith(Java.class).to(JavaService.class);

  14. binder.bind(Service.class).annotatedWith(com.edurt.sli.guice.multiple.Guice.class).to(GuiceService.class);

  15. }).getInstance(Application.class);

  16. application.guice.print("sss");

  17. application.java.print("sss");

  18. }


  19. }

我們運行程序輸出

  
  
  
  1. Guice Service sss

  2. Java Service sss

我們注意看 binder的配置中,我們將註解與實際的實現類綁定到了一起,這樣就實現了綁定多接口實現的功能。

注意:在本次程序中我們使用的是lambda表達式進行的代碼編程,需要jdk1.8及以上版本

靜態代碼注入


我們如果需要進行靜態代碼注入服務該怎麼寫呢?我們參照以前講解的 Guice依賴注入(構造函數注入)資源中,我們創建一個 ApplicationStatic類進行static的注入,代碼如下

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. import com.google.inject.Inject;


  3. public class ApplicationStatic {


  4. @Inject

  5. @Java

  6. public static Service java;


  7. @Inject

  8. @com.edurt.sli.guice.multiple.Guice

  9. public static Service guice;


  10. public static void main(String[] args) {

  11. com.google.inject.Guice.createInjector(binder -> {

  12. binder.bind(Service.class).annotatedWith(Java.class).to(JavaService.class);

  13. binder.bind(Service.class).annotatedWith(com.edurt.sli.guice.multiple.Guice.class).to(GuiceService.class);

  14. binder.requestStaticInjection(ApplicationStatic.class);

  15. });

  16. ApplicationStatic.guice.print("sss");

  17. ApplicationStatic.java.print("sss");

  18. }


  19. }

我們只需要在binder階段將我們的主類注入到guice容器中,也就是我們看到的 binder.requestStaticInjection(ApplicationStatic.class);代碼,運行程序輸出以下內容

  
  
  
  1. Guice Service sss

  2. Java Service sss

屬性綁定多接口


先看一下多接口綁定的示例

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. import com.google.inject.Guice;

  3. import com.google.inject.Inject;


  4. public class ApplicationMultipleProperty {


  5. @Inject

  6. public Service java;


  7. @Inject

  8. public Service guice;


  9. public static void main(String[] args) {

  10. ApplicationMultipleProperty application = Guice.createInjector(binder -> {

  11. binder.bind(Service.class).annotatedWith(Java.class).to(JavaService.class);

  12. binder.bind(Service.class).annotatedWith(com.edurt.sli.guice.multiple.Guice.class).to(GuiceService.class);

  13. }).getInstance(ApplicationMultipleProperty.class);

  14. application.guice.print("sss");

  15. application.java.print("sss");

  16. }


  17. }

運行以上代碼,就會出現以下錯誤

  
  
  
  1. Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors:


  2. 1) No implementation for com.edurt.sli.guice.multiple.Service was bound.

  3. Did you mean?

  4. * com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Java

  5. * com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Guice

  6. while locating com.edurt.sli.guice.multiple.Service

  7. for field at com.edurt.sli.guice.multiple.Application.guice(Application.java:6)

  8. while locating com.edurt.sli.guice.multiple.Application


  9. 2) No implementation for com.edurt.sli.guice.multiple.Service was bound.

  10. Did you mean?

  11. * com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Java

  12. * com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Guice

  13. while locating com.edurt.sli.guice.multiple.Service

  14. for field at com.edurt.sli.guice.multiple.Application.java(Application.java:6)

  15. while locating com.edurt.sli.guice.multiple.Application


  16. 2 errors

  17. at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1120)

  18. at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1078)

  19. at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1131)

  20. at com.edurt.sli.guice.multiple.Application.main(Application.java:18)

這是因爲我們使用了屬性綁定了多接口實現,導致guice無法識別具體是哪個實現類,不過guice是強大的這種問題也被考慮到了,只需要使用 @Named模板生成註解即可解決,我們姜代碼修改爲以下內容

  
  
  
  1. package com.edurt.sli.guice.multiple;


  2. import com.google.inject.Guice;

  3. import com.google.inject.Inject;

  4. import com.google.inject.name.Named;

  5. import com.google.inject.name.Names;


  6. public class ApplicationMultipleProperty {


  7. @Inject

  8. @Named("Java")

  9. public Service java;


  10. @Inject

  11. @Named("Guice")

  12. public Service guice;


  13. public static void main(String[] args) {

  14. ApplicationMultipleProperty application = Guice.createInjector(binder -> {

  15. binder.bind(Service.class).annotatedWith(Names.named("Java")).to(JavaService.class);

  16. binder.bind(Service.class).annotatedWith(Names.named("Guice")).to(GuiceService.class);

  17. }).getInstance(ApplicationMultipleProperty.class);

  18. application.guice.print("sss");

  19. application.java.print("sss");

  20. }


  21. }

運行程序後,輸出以下結果

  
  
  
  1. Guice Service sss

  2. Java Service sss

這個示例也很好理解,其實我們只是做了兩步操作

  • 在綁定實現的時候使用 annotatedWith(Names.named("Java"))進行對該服務實現做名稱標誌

  • 在需要使用服務實現的地方使用 @Named("Java")進行服務的引用即可

打包文件部署


  • 打包數據

  
  
  
  1. mvn clean package -Dmaven.test.skip=true -X

運行打包後的文件即可

  
  
  
  1. java -jar target/guice-binder-multiple-1.0.0.jar

源碼地址


  • GitHub

  • Gitee


本文分享自微信公衆號 - Spring中文網(china-spring-all)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章