- Google Guice 教程
- Guice - 首頁
- Guice - 概述
- Guice - 環境搭建
- Guice - 第一個應用
- 繫結示例
- Guice - 連結繫結
- Guice - 繫結註解
- Guice - @Named 繫結
- Guice - 常量繫結
- Guice - @Provides 註解
- Guice - Provider 類
- Guice - 建構函式繫結
- Guice - 內建繫結
- Guice - 即時繫結
- 注入示例
- Guice - 建構函式注入
- Guice - 方法注入
- Guice - 欄位注入
- Guice - 可選注入
- Guice - 按需注入
- 其他示例
- Guice - 作用域
- Guice - AOP
- Guice 有用資源
- Guice - 快速指南
- Guice - 有用資源
- Guice - 討論
Google Guice 快速指南
Google Guice - 概述
Guice 是一個開源的、基於 Java 的依賴注入框架。它非常輕量級,並且由 Google 積極開發/維護。
依賴注入
每個基於 Java 的應用程式都有一些物件協同工作,以向終端使用者呈現一個可執行的應用程式。在編寫複雜的 Java 應用程式時,應用程式類應該儘可能獨立於其他 Java 類,以增加重用這些類的可能性,並在單元測試期間獨立於其他類對其進行測試。依賴注入(有時稱為連線)有助於將這些類粘合在一起,同時保持它們的獨立性。
假設您有一個應用程式,其中包含一個文字編輯器元件,並且您希望提供拼寫檢查功能。您的標準程式碼如下所示:
public class TextEditor {
private SpellChecker spellChecker;
public TextEditor() {
spellChecker = new SpellChecker();
}
}
我們在這裡所做的是,在 TextEditor 和 SpellChecker 之間建立了一個依賴關係。在控制反轉場景中,我們將改為執行以下操作:
public class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
}
在這裡,TextEditor 不應該擔心 SpellChecker 的實現。SpellChecker 將獨立實現,並在 TextEditor 例項化時提供給 TextEditor。
使用 Guice 進行依賴注入(繫結)
依賴注入由 Guice 繫結控制。Guice 使用繫結將物件型別對映到它們的實際實現。這些繫結在模組中定義。模組是繫結集合,如下所示
public class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
/*
* Bind SpellChecker binding to WinWordSpellChecker implementation
* whenever spellChecker dependency is used.
*/
bind(SpellChecker.class).to(WinWordSpellChecker.class);
}
}
模組是 Injector 的核心構建塊,Injector 是 Guice 的物件圖構建器。第一步是建立一個 Injector,然後我們可以使用 Injector 獲取物件。
public static void main(String[] args) {
/*
* Guice.createInjector() takes Modules, and returns a new Injector
* instance. This method is to be called once during application startup.
*/
Injector injector = Guice.createInjector(new TextEditorModule());
/*
* Build object using injector
*/
TextEditor textEditor = injector.getInstance(TextEditor.class);
}
在上面的示例中,TextEditor 類的物件圖由 Guice 構造,並且此圖包含 TextEditor 物件及其依賴項作為 WinWordSpellChecker 物件。
Google Guice - 環境搭建
本地環境搭建
如果您仍然希望為 Java 程式語言設定環境,那麼本節將指導您如何在機器上下載和設定 Java。請按照下面提到的步驟設定環境。
Java SE 可從以下連結免費獲取 下載 Java。因此,您可以根據您的作業系統下載一個版本。
按照說明下載 Java 並執行.exe檔案以在您的機器上安裝 Java。在您的機器上安裝 Java 後,您需要設定環境變數以指向正確的安裝目錄:
為 Windows 2000/XP 設定路徑
我們假設您已將 Java 安裝在c:\Program Files\java\jdk目錄中:
右鍵單擊“我的電腦”,然後選擇“屬性”。
在“高階”選項卡下單擊“環境變數”按鈕。
現在,修改“Path”變數,使其還包含 Java 可執行檔案的路徑。例如,如果路徑當前設定為“C:\WINDOWS\SYSTEM32”,則將您的路徑更改為“C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin”。
為 Windows 95/98/ME 設定路徑
我們假設您已將 Java 安裝在c:\Program Files\java\jdk目錄中:
編輯“C:\autoexec.bat”檔案,並在末尾新增以下行:“SET PATH=%PATH%;C:\Program Files\java\jdk\bin”
為 Linux、UNIX、Solaris、FreeBSD 設定路徑
環境變數 PATH 應設定為指向 Java 二進位制檔案安裝的位置。如果您在執行此操作時遇到問題,請參閱您的 shell 文件。
例如,如果您使用 bash 作為您的 shell,則您將在“.bashrc”的末尾新增以下行:'export PATH=/path/to/java:$PATH'
流行的 Java 編輯器
要編寫 Java 程式,您需要一個文字編輯器。市場上有很多複雜的 IDE 可供使用。但就目前而言,您可以考慮以下其中之一:
記事本 - 在 Windows 機器上,您可以使用任何簡單的文字編輯器,如記事本(本教程推薦使用),TextPad。
Netbeans - 它是一個開源且免費的 Java IDE,可以從 https://www.netbeans.org/index.html 下載。
Eclipse - 它也是一個由 Eclipse 開源社群開發的 Java IDE,可以從 https://www.eclipse.org/ 下載。
Google Guice 環境
下載最新版本的 Google Guice 和相關的 jar 檔案。
在編寫本教程時,我們已將它們複製到 C:\>Google 資料夾中。
| 作業系統 | 歸檔名稱 |
|---|---|
| Windows | guice-4.1.0.jar;aopalliance-1.0.jar;guava-16.0.1.jar;javax.inject-1.jar |
| Linux | guice-4.1.0.jar;aopalliance-1.0.jar;guava-16.0.1.jar;javax.inject-1.jar |
| Mac | guice-4.1.0.jar;aopalliance-1.0.jar;guava-16.0.1.jar;javax.inject-1.jar |
設定 CLASSPATH 變數
設定CLASSPATH環境變數以指向 Guice jar 檔案的位置。假設您已將 Guice 和相關的 jar 檔案儲存在不同作業系統的 Google 資料夾中,如下所示。
| 作業系統 | 輸出 |
|---|---|
| Windows | 將環境變數 CLASSPATH 設定為 %CLASSPATH%;C:\Google\guice-4.1.0.jar;C:\Google\aopalliance-1.0.jar;C:\Google\guava-16.0.1.jar;C:\Google\javax.inject-1.jar;.; |
| Linux | export CLASSPATH=$CLASSPATH:Google/guice-4.1.0.jar:Google/aopalliance-1.0.jar:Google/guava-16.0.1.jar:Google/javax.inject-1.jar:. |
| Mac | export CLASSPATH=$CLASSPATH:Google/guice-4.1.0.jar:Google/aopalliance-1.0.jar:Google/guava-16.0.1.jar:Google/javax.inject-1.jar:. |
Google Guice - 第一個應用
讓我們建立一個基於控制檯的示例應用程式,我們將逐步演示使用 Guice 繫結機制進行依賴注入。
步驟 1:建立介面
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
步驟 2:建立實現
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
步驟 3:建立繫結模組
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
步驟 4:建立具有依賴關係的類
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
步驟 5:建立 Injector
Injector injector = Guice.createInjector(new TextEditorModule());
步驟 6:獲取依賴關係已滿足的物件。
TextEditor editor = injector.getInstance(TextEditor.class);
步驟 7:使用該物件。
editor.makeSpellCheck();
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling.
Google Guice - 連結繫結
在連結繫結中,Guice 將型別對映到其實現。在下面的示例中,我們已將 SpellChecker 介面與其實現 SpellCheckerImpl 對映。
bind(SpellChecker.class).to(SpellCheckerImpl.class);
我們還可以將具體類對映到其子類。請參見下面的示例
bind(SpellCheckerImpl.class).to(WinWordSpellCheckerImpl.class);
在這裡,我們已連結繫結。讓我們在完整示例中檢視結果。
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
bind(SpellCheckerImpl.class).to(WinWordSpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
//subclass of SpellCheckerImpl
class WinWordSpellCheckerImpl extends SpellCheckerImpl{
@Override
public void checkSpelling() {
System.out.println("Inside WinWordSpellCheckerImpl.checkSpelling." );
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside WinWordSpellCheckerImpl.checkSpelling.
Google Guice - 繫結註解
我們可以將型別與其實現繫結。如果我們希望將型別與多個實現對映,我們也可以建立自定義註解。請參見下面的示例以瞭解該概念。
建立繫結註解
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
@interface WinWord {}
@BindingAnnotation - 將註解標記為繫結註解。
@Target - 標記註解的適用性。
@Retention - 將註解的可用性標記為執行時。
使用繫結註解進行對映
bind(SpellChecker.class).annotatedWith(WinWord.class).to(WinWordSpellCheckerImpl.class);
使用繫結註解注入
@Inject
public TextEditor(@WinWord SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import java.lang.annotation.Target;
import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
@interface WinWord {}
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(@WinWord SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).annotatedWith(WinWord.class)
.to(WinWordSpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
//subclass of SpellCheckerImpl
class WinWordSpellCheckerImpl extends SpellCheckerImpl{
@Override
public void checkSpelling() {
System.out.println("Inside WinWordSpellCheckerImpl.checkSpelling." );
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside WinWordSpellCheckerImpl.checkSpelling.
Google Guice - Named 繫結
Guice 還提供了另一種無需建立自定義註解即可對映繫結的方法。它允許使用 @Named 註解。
使用 named 註解進行對映
bind(SpellChecker.class).annotatedWith(Names.named("OpenOffice")).to(OpenOfficeWordSpellCheckerImpl.class);
使用 @Named 註解注入
@Inject
public TextEditor(@Named("OpenOffice") SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(@Named("OpenOffice") SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).annotatedWith(Names.named("OpenOffice"))
.to(OpenOfficeWordSpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
//subclass of SpellCheckerImpl
class OpenOfficeWordSpellCheckerImpl extends SpellCheckerImpl{
@Override
public void checkSpelling() {
System.out.println("Inside OpenOfficeWordSpellCheckerImpl.checkSpelling." );
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside OpenOfficeWordSpellCheckerImpl.checkSpelling.
Google Guice - 常量繫結
Guice 提供了一種使用值物件或常量建立繫結的方法。考慮我們希望配置 JDBC url 的情況。
使用 @Named 註解注入
@Inject
public void connectDatabase(@Named("JBDC") String dbUrl) {
//...
}
這可以使用 toInstance() 方法實現。
bind(String.class).annotatedWith(Names.named("JBDC")).toInstance("jdbc:mysql://:5326/emp");
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeConnection();
}
}
class TextEditor {
private String dbUrl;
@Inject
public TextEditor(@Named("JDBC") String dbUrl) {
this.dbUrl = dbUrl;
}
public void makeConnection(){
System.out.println(dbUrl);
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://:5326/emp");
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
jdbc:mysql://:5326/emp
Google Guice - @Provides 註解
Guice 提供了一種使用 @provides 方法建立複雜物件繫結的方法。
@Provides
public SpellChecker provideSpellChecker(){
String dbUrl = "jdbc:mysql://:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
此方法是繫結模組的一部分,並提供要對映的複雜物件。請參見下面的完整示例。
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provides;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {}
@Provides
public SpellChecker provideSpellChecker(){
String dbUrl = "jdbc:mysql://:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
private String user;
private Integer timeout;
@Inject
public SpellCheckerImpl(String dbUrl,
String user,
Integer timeout){
this.dbUrl = dbUrl;
this.user = user;
this.timeout = timeout;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
System.out.println(user);
System.out.println(timeout);
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp user 100
Google Guice - Provider 介面
隨著 @provides 方法變得越來越複雜,這些方法可以使用 Provider 介面移動到單獨的類中。
class SpellCheckerProvider implements Provider<SpellChecker>{
@Override
public SpellChecker get() {
String dbUrl = "jdbc:mysql://:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
下一步是將 Provider 對映到型別。
bind(SpellChecker.class).toProvider(SpellCheckerProvider.class);
請參見下面的完整示例。
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class)
.toProvider(SpellCheckerProvider.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
private String user;
private Integer timeout;
@Inject
public SpellCheckerImpl(String dbUrl,
String user,
Integer timeout){
this.dbUrl = dbUrl;
this.user = user;
this.timeout = timeout;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
System.out.println(user);
System.out.println(timeout);
}
}
class SpellCheckerProvider implements Provider<SpellChecker>{
@Override
public SpellChecker get() {
String dbUrl = "jdbc:mysql://:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp user 100
Google Guice - 建構函式繫結
Guice 提供了一種使用 toConstructor() 方法建立物件特定建構函式繫結的方法。
@Override
protected void configure() {
try {
bind(SpellChecker.class)
.toConstructor(SpellCheckerImpl.class.getConstructor(String.class));
} catch (NoSuchMethodException | SecurityException e) {
System.out.println("Required constructor missing");
}
}
請參見下面的完整示例。
完整示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
try {
bind(SpellChecker.class)
.toConstructor(SpellCheckerImpl.class.getConstructor(String.class));
} catch (NoSuchMethodException | SecurityException e) {
System.out.println("Required constructor missing");
}
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://:5326/emp");
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
public SpellCheckerImpl(){}
public SpellCheckerImpl(@Named("JDBC") String dbUrl){
this.dbUrl = dbUrl;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp
Google Guice - 內建繫結
Guice 為java.util.logging.Logger類提供了內建繫結。Logger 的名稱會自動設定為注入 Logger 的類的名稱。請參見下面的示例。
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import java.util.logging.Logger;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private Logger logger;
@Inject
public TextEditor( Logger logger) {
this.logger = logger;
}
public void makeSpellCheck(){
logger.info("In TextEditor.makeSpellCheck() method");
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Dec 20, 2017 12:51:05 PM TextEditor makeSpellCheck INFO: In TextEditor.makeSpellCheck() method
Google Guice - 即時繫結
由於繫結是在繫結模組中定義的,因此 Guice 在需要注入依賴項時會使用它們。如果繫結不存在,它可以嘗試建立即時繫結。繫結模組中存在的繫結稱為顯式繫結,優先順序更高,而即時繫結稱為隱式繫結。如果兩種型別的繫結都存在,則考慮使用顯式繫結進行對映。
以下是三種類型的即時繫結的示例。
| 繫結型別 | 描述 |
|---|---|
| 可注入的建構函式 | 非私有、無引數的建構函式有資格進行即時繫結。另一種方法是使用 @Inject 註解註釋建構函式。 |
| @ImplementatedBy 註解 | @ImplementatedBy 註解告訴 Guice 實現類。在這種情況下,繫結模組中不需要繫結。 |
| @ProvidedBy 註解 | @ProvidedBy 註解告訴 Guice 實現類的提供者。在這種情況下,繫結模組中不需要繫結。 |
Guice - 可注入的建構函式
非私有、無引數的建構函式有資格進行即時繫結。另一種方法是使用 @Inject 註解註釋建構函式。請參見示例
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://:5326/emp");
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Inject @Named("JDBC")
private String dbUrl;
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp
Guice - @ImplementatedBy 註解
@ImplementatedBy 註解告訴 Guice 實現類。在這種情況下,繫結模組中不需要繫結。請參見示例
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://:5326/emp");
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Inject @Named("JDBC")
private String dbUrl;
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp
Google Guice - @ProvidedBy 註解
@ProvidedBy 註解告訴 Guice 實現類的提供者。在這種情況下,繫結模組中不需要繫結。請參見示例
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.ProvidedBy;
import com.google.inject.Provider;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
}
}
@ProvidedBy(SpellCheckerProvider.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
private String user;
private Integer timeout;
@Inject
public SpellCheckerImpl(String dbUrl,
String user,
Integer timeout){
this.dbUrl = dbUrl;
this.user = user;
this.timeout = timeout;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
System.out.println(user);
System.out.println(timeout);
}
}
class SpellCheckerProvider implements Provider<SpellChecker>{
@Override
public SpellChecker get() {
String dbUrl = "jdbc:mysql://:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp user 100
Google Guice - 建構函式注入
注入是將依賴項注入物件的過程。建構函式注入非常常見。在此過程中,依賴項作為引數注入到建構函式中。請參見下面的示例。
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling.
Google Guice - 方法注入
注入是將依賴項注入物件的過程。方法注入用於將值物件作為依賴項設定到物件中。請參見下面的示例。
示例
建立一個名為 GuiceTester 的 Java 類。
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://:5326/emp");
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
public SpellCheckerImpl(){}
@Inject
public void setDbUrl(@Named("JDBC") String dbUrl){
this.dbUrl = dbUrl;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp
Google Guice - 欄位注入
注入是將依賴項注入物件的過程。欄位注入用於將值物件作為依賴項設定到物件的欄位中。請參見下面的示例。
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://:5326/emp");
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Inject @Named("JDBC")
private String dbUrl;
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp
Google Guice - 可選注入
注入是將依賴項注入物件的過程。可選注入意味著如果存在則注入依賴項。方法和欄位注入可以是可選依賴項,如果依賴項不存在,則應具有一些預設值。請參見下面的示例。
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl = "jdbc:mysql://:5326/emp";
public SpellCheckerImpl(){}
@Inject(optional=true)
public void setDbUrl(@Named("JDBC") String dbUrl){
this.dbUrl = dbUrl;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
輸出
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling. jdbc:mysql://:5326/emp
Google Guice - 按需注入
注入是將依賴項注入物件的過程。方法和欄位注入可用於使用injector.injectMembers()方法使用現有物件進行初始化。請參見下面的示例。
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
SpellChecker spellChecker = new SpellCheckerImpl();
injector.injectMembers(spellChecker);
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public void setSpellChecker(SpellChecker spellChecker){
this.spellChecker = spellChecker;
}
public TextEditor() { }
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
編譯並執行該檔案,您將看到以下輸出。
Inside checkSpelling.
Google Guice - 作用域
Guice 在提供值時每次都會返回一個新例項,這是其預設行為。它可以透過作用域進行配置。以下是 Guice 支援的作用域
@Singleton - 應用程式生命週期內單個例項。@Singleton 物件需要是執行緒安全的。
@SessionScoped - Web 應用程式特定會話的單個例項。@SessionScoped 物件需要是執行緒安全的。
@RequestScoped - Web 應用程式特定請求的單個例項。@RequestScoped 物件不需要是執行緒安全的。
應用作用域的方式。
以下是應用作用域的方式。
在類級別
@Singleton
class SpellCheckerImpl implements SpellChecker {
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
在配置級別
bind(SpellChecker.class).to(SpellCheckerImpl.class).in(Singleton.class);
在方法級別
@Provides @Singleton
public SpellChecker provideSpellChecker(){
String dbUrl = "jdbc:mysql://:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
示例
讓我們看看類級別作用域的實際應用。
使用 @Singleton 註解的結果
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
SpellChecker spellChecker = new SpellCheckerImpl();
injector.injectMembers(spellChecker);
TextEditor editor = injector.getInstance(TextEditor.class);
System.out.println(editor.getSpellCheckerId());
TextEditor editor1 = injector.getInstance(TextEditor.class);
System.out.println(editor1.getSpellCheckerId());
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public void setSpellChecker(SpellChecker spellChecker){
this.spellChecker = spellChecker;
}
public TextEditor() { }
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
public double getSpellCheckerId(){
return spellChecker.getId();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
interface SpellChecker {
public double getId();
public void checkSpelling();
}
@Singleton
class SpellCheckerImpl implements SpellChecker {
double id;
public SpellCheckerImpl(){
id = Math.random();
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
@Override
public double getId() {
return id;
}
}
編譯並執行檔案,您可能會看到以下輸出。
0.3055839187063575 0.3055839187063575
不使用 @Singleton 註解的結果
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
SpellChecker spellChecker = new SpellCheckerImpl();
injector.injectMembers(spellChecker);
TextEditor editor = injector.getInstance(TextEditor.class);
System.out.println(editor.getSpellCheckerId());
TextEditor editor1 = injector.getInstance(TextEditor.class);
System.out.println(editor1.getSpellCheckerId());
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public void setSpellChecker(SpellChecker spellChecker){
this.spellChecker = spellChecker;
}
public TextEditor() { }
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
public double getSpellCheckerId(){
return spellChecker.getId();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
interface SpellChecker {
public double getId();
public void checkSpelling();
}
class SpellCheckerImpl implements SpellChecker {
double id;
public SpellCheckerImpl(){
id = Math.random();
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
@Override
public double getId() {
return id;
}
}
編譯並執行檔案,您可能會看到以下輸出。
0.556007079571739 0.22095011760351602
Google Guice - AOP
AOP,面向切面程式設計,它將程式邏輯分解成不同的部分,稱為關注點。跨越應用程式多個點的函式稱為橫切關注點,這些橫切關注點在概念上與應用程式的業務邏輯是分開的。日誌記錄、審計、宣告式事務、安全、快取等是各種常見的良好方面示例。
OOP 中模組化的關鍵單元是類,而在 AOP 中,模組化的單元是方面。依賴注入幫助您將應用程式物件彼此解耦,而 AOP 幫助您將橫切關注點與受其影響的物件解耦。AOP 就像 Perl、.NET、Java 等程式語言中的觸發器。Guice 提供攔截器來攔截應用程式。例如,當執行方法時,您可以在方法執行之前或之後新增額外的功能。
重要類
Matcher - Matcher 是一個介面,用於接受或拒絕值。在 Guice AOP 中,我們需要兩個匹配器:一個用於定義哪些類參與,另一個用於這些類的方法。
MethodInterceptor - 當呼叫匹配的方法時,會執行 MethodInterceptors。它們可以檢查呼叫:方法、其引數和接收例項。我們可以執行橫切邏輯,然後委託給底層方法。最後,我們可以檢查返回值或異常並返回。
示例
建立一個名為 GuiceTester 的 Java 類。
GuiceTester.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.matcher.Matchers;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
bindInterceptor(Matchers.any(),
Matchers.annotatedWith(CallTracker.class),
new CallTrackerService());
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override @CallTracker
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)
@interface CallTracker {}
class CallTrackerService implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before " + invocation.getMethod().getName());
Object result = invocation.proceed();
System.out.println("After " + invocation.getMethod().getName());
return result;
}
}
編譯並執行檔案,您可能會看到以下輸出。
Before checkSpelling Inside checkSpelling. After checkSpelling