Guice 简明教程

Google Guice - Quick Guide

Google Guice - Overview

Guice 是基于 Java 的开源依赖注入框架。它非常轻量,并且由 Google 积极开发/管理。

Dependency Injection

每个基于 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。

Dependency Injection using Guice (Binding)

依赖注入受 Guice Binding 控制。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);
   }
}

模块是 Guice 对象图生成器的 Injector 的核心构建模块。第一步是创建 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 - Environment Setup

Local Environment Setup

如果您仍然愿意为 Java 编程语言设置您的环境,则本节指导您如何在您的机器上下载并设置 Java。请按照下面提到的步骤设置环境。

Java SE 可以从链接 Download Java 中免费获取。因此,您可以根据自己的操作系统下载版本。

按照说明下载 Java 并运行 .exe 以在您的计算机上安装 Java。安装计算机上的 Java 后,您需要设置环境变量以指向正确的安装目录 −

Setting up the Path for Windows 2000/XP

我们假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 −

  1. 右键单击“我的电脑”,然后选择“属性”。

  2. 单击“高级”选项卡下的“环境变量”按钮。

  3. 现在,更改“路径”变量,使其也包含指向 Java 可执行文件的路径。例如,如果路径目前设置为“C:\WINDOWS\SYSTEM32”,那么将您的路径更改为“C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin”。

Setting up the Path for Windows 95/98/ME

我们假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 −

  1. 编辑 ‘C:\autoexec.bat’ 文件并在末尾添加以下行 − ‘SET PATH=%PATH%;C:\Program Files\java\jdk\bin’

Setting up the Path for Linux, UNIX, Solaris, FreeBSD

环境变量 PATH 应设置为指向已安装 Java 二进制文件的位置。如果你在这方面遇到问题,请参阅 shell 文档。

例如,如果您用 bash 作为您的 shell,则您将向您 '.bashrc: export PATH=/path/to/java:$PATH' 的末尾添加以下行

要编写 Java 程序,您需要一个文本编辑器。市场中有许多高级集成开发环境可用。但目前,您可以考虑以下选项之一 −

  1. Notepad − 在 Windows 计算机上,您可以使用任何简单的文本编辑器,例如记事本(推荐用于本教程)、TextPad。

  2. Netbeans - 它是一款开源的免费 Java IDE,可以从 https://www.netbeans.org/index.html 下载。

  3. Eclipse - 它也是一款由 Eclipse 开源社区开发的 Java IDE,可以从 https://www.eclipse.org/ 下载。

Google Guice Environment

下载 Google Guice 最新版本及相关 jar 文件。

在我们编写本教程时,已将它们拷贝到 C:\>Google 文件夹中。

OS

Archive name

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

Set CLASSPATH Variable

设置 CLASSPATH 环境变量以指向 Guice jar 位置。我们假设您已按照如下方式将 Guice 及相关 jar 存储在不同操作系统的 Google 文件夹中。

OS

Output

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 - First Application

让我们创建一个基于示例控制台的应用程序,我们会逐步使用 Guice 绑定机制演示依赖项注入。

Step 1: Create Interface

//spell checker interface
interface SpellChecker {
   public void checkSpelling();
}

Step 2: Create Implementation

//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
   @Override
   public void checkSpelling() {
      System.out.println("Inside checkSpelling." );
   }
}

Step 3: Create Bindings Module

//Binding Module
class TextEditorModule extends AbstractModule {
   @Override
   protected void configure() {
      bind(SpellChecker.class).to(SpellCheckerImpl.class);
   }
}

Step 4: Create Class with dependency

class TextEditor {
   private SpellChecker spellChecker;
   @Inject
   public TextEditor(SpellChecker spellChecker) {
      this.spellChecker = spellChecker;
   }
   public void makeSpellCheck(){
      spellChecker.checkSpelling();
   }
}

Step 5: Create Injector

Injector injector = Guice.createInjector(new TextEditorModule());

Step 6: Get Object with dependency fulfilled.

TextEditor editor = injector.getInstance(TextEditor.class);

Step 7: Use the object.

editor.makeSpellCheck();

Complete Example

创建名为 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." );
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.

Google Guice - Linked Bindings

在链接绑定中,Guice 将类型映射到其实现。在以下示例中,我们已经使用其实现 SpellCheckerImpl 映射了 SpellChecker 界面。

bind(SpellChecker.class).to(SpellCheckerImpl.class);

用户也可以将具体类映射到其子类。请参阅以下示例:

bind(SpellCheckerImpl.class).to(WinWordSpellCheckerImpl.class);

在这里我们已经链接了绑定。让我们在完整示例中了解结果。

Complete Example

创建名为 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." );
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside WinWordSpellCheckerImpl.checkSpelling.

Google Guice - Binding Annotations

由于我们能够使用其实现绑定一个类型。如果我们希望使用多个实现映射一个类型,我们也可以创建自定义注释。请参阅以下示例以了解此概念。

Create a binding annotation

@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
@interface WinWord {}
  1. @BindingAnnotation - 标记注释作为绑定注释。

  2. @Target - 标记注释的适用性。

  3. @Retention - 将注释的可用性标记为运行时。

Mapping using binding annotation

bind(SpellChecker.class).annotatedWith(WinWord.class).to(WinWordSpellCheckerImpl.class);

Inject using binding annotation

@Inject
public TextEditor(@WinWord SpellChecker spellChecker) {
   this.spellChecker = spellChecker;
}

Complete Example

创建名为 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." );
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside WinWordSpellCheckerImpl.checkSpelling.

Google Guice - Named Bindings

Guice 还提供了另一种映射绑定而不创建自定义注释的方法。它允许使用 @Named 注释。

Mapping using named annotation

bind(SpellChecker.class).annotatedWith(Names.named("OpenOffice")).to(OpenOfficeWordSpellCheckerImpl.class);

Inject using @Named annotation

@Inject
public TextEditor(@Named("OpenOffice") SpellChecker spellChecker) {
   this.spellChecker = spellChecker;
}

Complete Example

创建名为 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." );
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside OpenOfficeWordSpellCheckerImpl.checkSpelling.

Google Guice - Constant Bindings

Guice 提供了一种通过值对象或常量创建绑定信息的方法。以我们想配置 JDBC url 为例。

Inject using @Named annotation

@Inject
public void connectDatabase(@Named("JBDC") String dbUrl) {
   //...
}

这可以通过 toInstance() 方法实现。

bind(String.class).annotatedWith(Names.named("JBDC")).toInstance("jdbc:mysql://localhost:5326/emp");

Complete Example

创建名为 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://localhost:5326/emp");
   }
}

Output

编译运行该文件,您会看到以下输出内容。

jdbc:mysql://localhost:5326/emp

Google Guice - @Provides Annotation

Guice 提供了一种方法,可以使用 @provides 方法创建具有复杂对象的绑定。

@Provides
public SpellChecker provideSpellChecker(){
   String dbUrl = "jdbc:mysql://localhost:5326/emp";
   String user = "user";
   int timeout = 100;
   SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
   return SpellChecker;
}

此方法作为 Binding Module 的一部分,并提供要映射的复杂对象。请参见以下完整示例。

Complete Example

创建名为 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://localhost: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);
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
user
100

Google Guice - Provider Interface

随着 @provides 方法变得更加复杂,这些方法可以使用 Provider 接口移动到单独的类中。

class SpellCheckerProvider implements Provider<SpellChecker>{
   @Override
   public SpellChecker get() {
      String dbUrl = "jdbc:mysql://localhost:5326/emp";
      String user = "user";
      int timeout = 100;
      SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
      return SpellChecker;
   }
}

下一步是将提供程序映射到类型。

bind(SpellChecker.class).toProvider(SpellCheckerProvider.class);

请参见以下完整示例。

Complete Example

创建名为 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://localhost:5326/emp";
      String user = "user";
      int timeout = 100;

      SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
      return SpellChecker;
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
user
100

Google Guice - Constructor Bindings

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");
   }
}

请参见以下完整示例。

Complete Example

创建名为 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://localhost: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);
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp

Google Guice - Inbuilt Bindings

Guice 为 java.util.logging.Logger 类提供内置绑定。Logger 的名称会自动设置为 Logger 被注入到的类的名称。请参见以下示例。

Example

创建名为 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() {
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Dec 20, 2017 12:51:05 PM TextEditor makeSpellCheck
INFO: In TextEditor.makeSpellCheck() method

Google Guice - Just-In-Time Bindings

在绑定模块中定义绑定信息时,Guice 会在需要注入依赖项时使用这些信息。如果没有绑定信息,它会尝试创建即时绑定信息。在绑定模块中存在的绑定信息称为显式绑定信息,具有更高的优先级,而即时绑定信息称为隐式绑定信息。如果两种类型的信息都存在,则会考虑显式绑定信息进行映射。

以下是三种即时绑定信息的示例。

Binding Type

Description

Injectable Constructors

非私有的无参数构造函数适于即时绑定。另一种方法是使用 @Inject 注释为某个构造函数添加注释。

@ImplementatedBy annotation

@ImplementatedBy 注释告诉 Guice 有关实现类的信息。在这种情况下,Binding Module 中不需要绑定。

@ProvidedBy annotation

@ProvidedBy 注释将实现类的提供程序告知 guice。在这种情况下,不需要在绑定模块中进行绑定。

Guice - Injectable Constructors

非私有的无参数构造函数符合即时绑定条件。另一种方法是使用 @Inject 注释注释构造函数。请参阅示例:

Example

创建名为 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://localhost: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);
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp

Guice - @ImplementatedBy annotation

@ImplementatedBy 注释告诉 Guice 有关实现类的信息。在这种情况下,Binding Module 中不需要绑定。敬请参阅示例:

Example

创建名为 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://localhost: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);
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp

Google Guice - @ProvidedBy Annotation

@ProvidedBy 注释告诉 Guice 有关实现类的提供程序的信息。在这种情况下,Binding Module 中不需要绑定。敬请参阅示例:

Example

创建名为 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://localhost:5326/emp";
      String user = "user";
      int timeout = 100;

      SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
      return SpellChecker;
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
user
100

Google Guice - Constructor Injection

注入是向对象中注入依赖项的过程。构造函数注入非常普遍。在此过程中,依赖项以参数的形式注入到构造函数中。请参阅以下示例。

创建名为 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." );
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.

Google Guice - Method Injection

注入是将依赖注入到对象中的一个过程。方法注入用于将值对象作为依赖项设置到对象中。请参见以下示例。

Example

创建名为 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://localhost: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);
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp

Google Guice - Field Injection

注入是向对象中注入依赖项的过程。字段注入用于设置值对象作为某个对象的字段的依赖项。请参阅以下示例。

Example

创建名为 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://localhost: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);
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp

Google Guice - Optional Injection

注入是将依赖注入到对象中的一个过程。可选注入意味着在存在依赖项时注入该依赖项。方法和字段注入可能是可选的依赖项,并且在不存在依赖项时应该具有一些默认值。请参见以下示例。

Example

创建名为 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://localhost: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);
   }
}

Output

编译运行该文件,您会看到以下输出内容。

Inside checkSpelling.
jdbc:mysql://localhost:5326/emp

Google Guice - On Demand Injection

注入是向某个对象注入依赖的过程。使用 exiting 对象的 injector.injectMembers() 方法可以对方法和字段进行注入。请参阅以下示例。

Example

创建名为 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 - Scopes

Guice 会在其默认行为作为其值时,每次都返回一个新实例。它可以通过范围进行配置。以下是 Guice 支持的范围:

  1. @Singleton - 应用程序生命周期的单实例。@Singleton 对象需要是线程安全的。

  2. @SessionScoped - Web 应用程序特定会话的单实例。@SessionScoped 对象需要是线程安全的。

  3. @RequestScoped - Web 应用程序特定请求的单实例。@RequestScoped 对象不需要是线程安全的。

Way to apply scopes. Following are the ways to apply scopes.

At Class level

@Singleton
class SpellCheckerImpl implements SpellChecker {

   public SpellCheckerImpl(){}

   @Override
   public void checkSpelling() {
      System.out.println("Inside checkSpelling." );
   }
}

At Configuration level

   bind(SpellChecker.class).to(SpellCheckerImpl.class).in(Singleton.class);

At Method level

@Provides @Singleton
public SpellChecker provideSpellChecker(){

   String dbUrl = "jdbc:mysql://localhost:5326/emp";
   String user = "user";
   int timeout = 100;

   SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
   return SpellChecker;
}

Example

让我们在类级别中查看实际作用域。

Result With @Singleton Annotation

创建名为 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

Result Without @Singleton Annotation

创建名为 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

面向方面的编程 OAP,意味着将程序逻辑分解成不同的部分,所谓的关注点。跨越应用程序多个点的函数称为横切关注点,并且这些横切关注点在概念上与应用程序的业务逻辑是分离的。横切面有很多常见的例子,例如日志记录、审计、声明式交易、安全、缓存等。

面向对象编程中模块化的关键单元是类,而面向方面编程中模块化的单元是横切面。依赖注入帮助用户解耦应用程序对象,并且面向方面编程帮助用户解耦横切关注点和它们影响的对象。面向方面编程类似于 Perl、.NET、Java 和其他编程语言中的触发器。Guice 提供拦截器来拦截应用程序。例如,在执行方法时,用户可以在方法执行之前或之后添加额外功能。

Important Classes

  1. Matcher - Matcher 是接受或拒绝值的界面。在 Guice AOP 中,我们需要两个匹配器:一个用来定义参与的类,另一个针对这些类的函数。

  2. MethodInterceptor - 调用匹配方法时,执行 MethodInterceptors。它们可以检查调用:方法、其参数、以及方法接收的实例。我们可以执行横切逻辑,然后将其委托给底层方法。最后,我们可以检查返回值或异常并返回。

Example

创建名为 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