本教程主要詳細講解Guice依賴注入中的特性接口多實現,一般使用到guice的框架的插件機制都是基於該方式實現。
基礎環境
技術 | 版本 |
---|---|
Java | 1.8+ |
Guice | 4.2.3 |
初始化項目
初始化項目
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依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>learn-integration-guice</artifactId>
<groupId>com.edurt.sli.guice</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>guice-binder-multiple</artifactId>
<name>Guice依賴注入(接口多實現)</name>
<properties>
<system.java.version>1.8</system.java.version>
<guice.version>4.2.3</guice.version>
<lombok.version>1.18.2</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>${guice.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${plugin.maven.compiler.version}</version>
<configuration>
<source>${system.java.version}</source>
<target>${system.java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
guice
: guice就是我們核心要使用的依賴
接口多實現注入
如果一個接口有多個實現,如果單單通過 @Inject
和 Module
都難以直接實現,但多實現是經常會出現的,Guice提供了其它注入方式來解決此問題。
創建
com.edurt.sli.guice.multiple
文件夾,並在該文件夾下創建Service
接口文件,用於添加我們需要測試的函數
package com.edurt.sli.guice.multiple;
public interface Service {
void print(String source);
}
創建
Service
接口的實現類JavaService
和GuiceService
,用於實現接口中的方法,代碼如下
package com.edurt.sli.guice.multiple;
public class JavaService implements Service {
@Override
public void print(String source) {
System.out.println("Java Service " + source);
}
}
package com.edurt.sli.guice.multiple;
public class GuiceService implements Service {
@Override
public void print(String source) {
System.out.println("Guice Service " + source);
}
}
創建
Guice
和Java
註解類,用於提供guice框架標識
package com.edurt.sli.guice.multiple;
import com.google.inject.BindingAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Guice {
}
package com.edurt.sli.guice.multiple;
import com.google.inject.BindingAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Java {
}
創建用於測試注入的應用類
Application
,代碼如下
package com.edurt.sli.guice.multiple;
import com.google.inject.Guice;
import com.google.inject.Inject;
public class Application {
@Inject
@Java
public Service java;
@Inject
@com.edurt.sli.guice.multiple.Guice
public Service guice;
public static void main(String[] args) {
Application application = Guice.createInjector(binder -> {
binder.bind(Service.class).annotatedWith(Java.class).to(JavaService.class);
binder.bind(Service.class).annotatedWith(com.edurt.sli.guice.multiple.Guice.class).to(GuiceService.class);
}).getInstance(Application.class);
application.guice.print("sss");
application.java.print("sss");
}
}
我們運行程序輸出
Guice Service sss
Java Service sss
我們注意看 binder
的配置中,我們將註解與實際的實現類綁定到了一起,這樣就實現了綁定多接口實現的功能。
注意:在本次程序中我們使用的是lambda表達式進行的代碼編程,需要jdk1.8及以上版本
靜態代碼注入
我們如果需要進行靜態代碼注入服務該怎麼寫呢?我們參照以前講解的 Guice依賴注入(構造函數注入)
資源中,我們創建一個 ApplicationStatic
類進行static的注入,代碼如下
package com.edurt.sli.guice.multiple;
import com.google.inject.Inject;
public class ApplicationStatic {
@Inject
@Java
public static Service java;
@Inject
@com.edurt.sli.guice.multiple.Guice
public static Service guice;
public static void main(String[] args) {
com.google.inject.Guice.createInjector(binder -> {
binder.bind(Service.class).annotatedWith(Java.class).to(JavaService.class);
binder.bind(Service.class).annotatedWith(com.edurt.sli.guice.multiple.Guice.class).to(GuiceService.class);
binder.requestStaticInjection(ApplicationStatic.class);
});
ApplicationStatic.guice.print("sss");
ApplicationStatic.java.print("sss");
}
}
我們只需要在binder階段將我們的主類注入到guice容器中,也就是我們看到的 binder.requestStaticInjection(ApplicationStatic.class);
代碼,運行程序輸出以下內容
Guice Service sss
Java Service sss
屬性綁定多接口
先看一下多接口綁定的示例
package com.edurt.sli.guice.multiple;
import com.google.inject.Guice;
import com.google.inject.Inject;
public class ApplicationMultipleProperty {
@Inject
public Service java;
@Inject
public Service guice;
public static void main(String[] args) {
ApplicationMultipleProperty application = Guice.createInjector(binder -> {
binder.bind(Service.class).annotatedWith(Java.class).to(JavaService.class);
binder.bind(Service.class).annotatedWith(com.edurt.sli.guice.multiple.Guice.class).to(GuiceService.class);
}).getInstance(ApplicationMultipleProperty.class);
application.guice.print("sss");
application.java.print("sss");
}
}
運行以上代碼,就會出現以下錯誤
Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors:
1) No implementation for com.edurt.sli.guice.multiple.Service was bound.
Did you mean?
* com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Java
* com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Guice
while locating com.edurt.sli.guice.multiple.Service
for field at com.edurt.sli.guice.multiple.Application.guice(Application.java:6)
while locating com.edurt.sli.guice.multiple.Application
2) No implementation for com.edurt.sli.guice.multiple.Service was bound.
Did you mean?
* com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Java
* com.edurt.sli.guice.multiple.Service annotated with interface com.edurt.sli.guice.multiple.Guice
while locating com.edurt.sli.guice.multiple.Service
for field at com.edurt.sli.guice.multiple.Application.java(Application.java:6)
while locating com.edurt.sli.guice.multiple.Application
2 errors
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1120)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1078)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1131)
at com.edurt.sli.guice.multiple.Application.main(Application.java:18)
這是因爲我們使用了屬性綁定了多接口實現,導致guice無法識別具體是哪個實現類,不過guice是強大的這種問題也被考慮到了,只需要使用 @Named
模板生成註解即可解決,我們姜代碼修改爲以下內容
package com.edurt.sli.guice.multiple;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class ApplicationMultipleProperty {
@Inject
@Named("Java")
public Service java;
@Inject
@Named("Guice")
public Service guice;
public static void main(String[] args) {
ApplicationMultipleProperty application = Guice.createInjector(binder -> {
binder.bind(Service.class).annotatedWith(Names.named("Java")).to(JavaService.class);
binder.bind(Service.class).annotatedWith(Names.named("Guice")).to(GuiceService.class);
}).getInstance(ApplicationMultipleProperty.class);
application.guice.print("sss");
application.java.print("sss");
}
}
運行程序後,輸出以下結果
Guice Service sss
Java Service sss
這個示例也很好理解,其實我們只是做了兩步操作
在綁定實現的時候使用
annotatedWith(Names.named("Java"))
進行對該服務實現做名稱標誌在需要使用服務實現的地方使用
@Named("Java")
進行服務的引用即可
打包文件部署
打包數據
mvn clean package -Dmaven.test.skip=true -X
運行打包後的文件即可
java -jar target/guice-binder-multiple-1.0.0.jar
源碼地址
GitHub
Gitee
本文分享自微信公衆號 - Spring中文網(china-spring-all)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。