Guice 简明教程

Google Guice - Quick Guide

Google Guice - Overview

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

Guice is an open source, Java-based dependency injection framework. It is quiet lightweight and is actively developed/managed by Google.

Dependency Injection

每个基于 Java 的应用程序都有一些对象可以协同工作,以展示最终用户所看到的工作应用程序。在编写复杂的 Java 应用程序时,应用程序类应尽可能独立于其他 Java 类,以增加重用这些类并使其独立于其他类进行单​​元测试的可能性。依赖注入(或有时称为连接)有助于将这些类粘合在一起,同时又保持它们独立性。

Every Java-based application has a few objects that work together to present what the end-user sees as a working application. When writing a complex Java application, application classes should be as independent as possible of other Java classes to increase the possibility to reuse these classes and to test them independently of other classes while unit testing. Dependency Injection (or sometime called wiring) helps in gluing these classes together and at the same time keeping them independent.

考虑您有一个包含文本编辑器组件的应用程序,并且您希望提供拼写检查。您的标准代码将如下所示 −

Consider you have an application which has a text editor component and you want to provide a spell check. Your standard code would look something like this −

public class TextEditor {
   private SpellChecker spellChecker;

   public TextEditor() {
      spellChecker = new SpellChecker();
   }
}

我们在此处所做的是创建 TextEditor 和 SpellChecker 之间的依赖关系。在控制反转场景中,我们改为执行类似以下操作 −

What we’ve done here is, create a dependency between the TextEditor and the SpellChecker. In an inversion of control scenario, we would instead do something like this −

public class TextEditor {
   private SpellChecker spellChecker;

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

在此,TextEditor 应该不用担心 SpellChecker 的实现。SpellChecker 将独立实现,并且在 TextEditor 实例化时提供给 TextEditor。

Here, the TextEditor should not worry about SpellChecker implementation. The SpellChecker will be implemented independently and will be provided to the TextEditor at the time of TextEditor instantiation.

Dependency Injection using Guice (Binding)

依赖注入受 Guice Binding 控制。Guice 使用绑定将对象类型映射到其实际实现。这些绑定定义了一个模块。模块是一组绑定,如下所示:

Dependency Injection is controlled by the Guice Bindings. Guice uses bindings to map object types to their actual implementations. These bindings are defined a module. A module is a collection of bindings as shown below:

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 获取对象。

The Module is the core building block for an Injector which is Guice’s object-graph builder. First step is to create an injector and then we can use the injector to get the objects.

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 对象的依赖项。

In above example, TextEditor class object graph is constructed by Guice and this graph contains TextEditor object and its dependency as WinWordSpellChecker object.

Google Guice - Environment Setup

Local Environment Setup

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

If you are still willing to set up your environment for Java programming language, then this section guides you on how to download and set up Java on your machine. Please follow the steps mentioned below to set up the environment.

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

Java SE is freely available from the link Download Java. So you download a version based on your operating system.

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

Follow the instructions to download Java and run the .exe to install Java on your machine. Once you have installed Java on your machine, you would need to set environment variables to point to correct installation directories −

Setting up the Path for Windows 2000/XP

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

We are assuming that you have installed Java in c:\Program Files\java\jdk directory −

  1. Right-click on 'My Computer' and select 'Properties'.

  2. Click on the 'Environment variables' button under the 'Advanced' tab.

  3. Now, alter the 'Path' variable so that it also contains the path to the Java executable. Example, if the path is currently set to 'C:\WINDOWS\SYSTEM32', then change your path to read 'C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin'.

Setting up the Path for Windows 95/98/ME

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

We are assuming that you have installed Java in c:\Program Files\java\jdk directory −

  1. Edit the 'C:\autoexec.bat' file and add the following line at the end − 'SET PATH=%PATH%;C:\Program Files\java\jdk\bin'

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

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

Environment variable PATH should be set to point to where the Java binaries have been installed. Refer to your shell documentation if you have trouble doing this.

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

Example, if you use bash as your shell, then you would add the following line to the end of your '.bashrc: export PATH=/path/to/java:$PATH'

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

To write your Java programs, you need a text editor. There are many sophisticated IDEs available in the market. But for now, you can consider one of the following −

  1. Notepad − On Windows machine you can use any simple text editor like Notepad (Recommended for this tutorial), TextPad.

  2. Netbeans − It is a Java IDE that is open-source and free which can be downloaded from https://www.netbeans.org/index.html.

  3. Eclipse − It is also a Java IDE developed by the eclipse open-source community and can be downloaded from https://www.eclipse.org/.

Google Guice Environment

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

Download the latest version of Google Guice and related jar files.

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

At the time of writing this tutorial, we have copied them into C:\>Google folder.

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 文件夹中。

Set the CLASSPATH environment variable to point to the Guice jar location. Assuming, you have stored Guice and related jars in Google folder on various Operating Systems as follows.

OS

Output

Windows

Set the environment variable CLASSPATH to %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 绑定机制演示依赖项注入。

Let’s create a sample console based application where we’ll demonstrate dependency injection using Guice binding mechanism step by step.

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 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

Inside checkSpelling.

Google Guice - Linked Bindings

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

In Linked bindings, Guice maps a type to its implementation. In below example, we’ve mapped SpellChecker interface with its implementation SpellCheckerImpl.

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

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

We can also mapped the concrete class to its subclass. See the example below:

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

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

Here we’ve chained the bindings. Let’s see the result in complete example.

Complete Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

Inside WinWordSpellCheckerImpl.checkSpelling.

Google Guice - Binding Annotations

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

As we can bind a type with its implementation. In case we want to map a type with multiple implmentations, we can create custom annotation as well. See the below example to understand the concept.

Create a binding annotation

@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
@interface WinWord {}
  1. @BindingAnnotation - Marks annotation as binding annotation.

  2. @Target - Marks applicability of annotation.

  3. @Retention - Marks availablility of annotation as runtime.

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 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

Inside WinWordSpellCheckerImpl.checkSpelling.

Google Guice - Named Bindings

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

Guice provides another way also to map bindings without creating a custom annoation. It allows so using @Named annotation.

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 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

Inside OpenOfficeWordSpellCheckerImpl.checkSpelling.

Google Guice - Constant Bindings

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

Guice provides a way to create bindings with value objects or constants. Consider the case where we want to configure JDBC url.

Inject using @Named annotation

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

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

This can be achived using toInstance() method.

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

Complete Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

jdbc:mysql://localhost:5326/emp

Google Guice - @Provides Annotation

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

Guice provides a way to create bindings with complex objects using @provides method.

@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 的一部分,并提供要映射的复杂对象。请参见以下完整示例。

This methos is being part of Binding Module and provides the complex object to be mapped. See the complete example below.

Complete Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - Provider Interface

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

As @provides method becomes more complex, these methods can be moved to seperate classes using Provider interface.

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

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

Next step is to map the provider to type.

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

请参见以下完整示例。

See the complete example below.

Complete Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - Constructor Bindings

Guice 提供了一种方法,可以使用 toConstructor() 方法创建具有对象的特定构造函数的绑定。

Guice provides a way to create bindings with specific constructor of an object using toConstructor() method.

@Override
protected void configure() {
   try {
      bind(SpellChecker.class)
         .toConstructor(SpellCheckerImpl.class.getConstructor(String.class));
      } catch (NoSuchMethodException | SecurityException e) {
      System.out.println("Required constructor missing");
   }
}

请参见以下完整示例。

See the complete example below.

Complete Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - Inbuilt Bindings

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

Guice provides inbuilt binding for java.util.logging.Logger class. Logger’s name is automatically set to the name of the class into which the Logger is injected. See the example below.

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - Just-In-Time Bindings

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

As bindings are defined in Binding Module, Guice uses them whenever it needs to inject dependencies. In case bindings are not present, it can attempt to create just-in-time bindings. Bindings present in binding module are called explicit bindings and are of higher precedence whereas just-in-time bindings are called implicit bindings. If both type of bindings are present, explicit bindings are considered for mapping.

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

Following are the examples of three types of Just-in-time bindings.

Binding Type

Description

Injectable Constructors

Non-private, No-argument constructors are eligible for just-in-time bindings. Another way is to annotate a constructor with @Inject annotation.

@ImplementatedBy annotation

@ImplementatedBy annotation tells the guice about the implementation class. No binding is required in Binding Module in such a case.

@ProvidedBy annotation

@ProvidedBy annotation tells the guice about the provider of implementation class. No binding is required in Binding Module in such a case.

Guice - Injectable Constructors

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

Non-private, No-argument constructors are eligible for just-in-time bindings. Another way is to annotate a constructor with @Inject annotation. See the example:

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Guice - @ImplementatedBy annotation

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

@ImplementatedBy annotation tells the guice about the implementation class. No binding is required in Binding Module in such a case. See the example:

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - @ProvidedBy Annotation

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

@ProvidedBy annotation tells the guice about the provider of implementation class. No binding is required in Binding Module in such a case. See the example:

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - Constructor Injection

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

Injection is a process of injecting dependeny into an object. Constructor injection is quite common. In this process, dependency is injected as argument to the constructor. See the example below.

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

Inside checkSpelling.

Google Guice - Method Injection

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

Injection is a process of injecting dependeny into an object. Method injection is used to set value object as dependency to the object. See the example below.

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - Field Injection

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

Injection is a process of injecting dependeny into an object. Field injection is used to set value object as dependency to the field of an object. See the example below.

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - Optional Injection

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

Injection is a process of injecting dependeny into an object. Optional injection means injecting the dependency if exists. Method and Field injections may be optionally dependent and should have some default value if dependency is not present. See the example below.

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

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

Google Guice - On Demand Injection

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

Injection is a process of injecting dependeny into an object. Method and field injections can be used to initialize using exiting object using injector.injectMembers() method. See the example below.

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

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

Compile and run the file, you will see the following output.

Inside checkSpelling.

Google Guice - Scopes

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

Guice returns a new instance every time when it supplies a value as its default behaviour. It is configurable via scopes. Following are the scopes that Guice supports:

  1. @Singleton - Single instance for lifetime of the application. @Singleton object needs to be threadsafe.

  2. @SessionScoped - Single instance for a particular session of the web application. @SessionScoped object needs to be threadsafe.

  3. @RequestScoped - Single instance for a particular request of the web application. @RequestScoped object does not need to be threadsafe.

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

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

Let’s see the Scope at class level in action.

Result With @Singleton Annotation

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

编译并运行文件,用户可以看到以下输出。

Compile and run the file, you may see the following output.

0.3055839187063575
0.3055839187063575

Result Without @Singleton Annotation

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

编译并运行文件,用户可以看到以下输出。

Compile and run the file, you may see the following output.

0.556007079571739
0.22095011760351602

Google Guice - AOP

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

AOP, Aspect oriented programming entails breaking down program logic into distinct parts called so-called concerns. The functions that span multiple points of an application are called cross-cutting concerns and these cross-cutting concerns are conceptually separate from the application’s business logic. There are various common good examples of aspects like logging, auditing, declarative transactions, security, caching, etc.

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

The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Dependency Injection helps you decouple your application objects from each other and AOP helps you decouple cross-cutting concerns from the objects that they affect. AOP is like triggers in programming languages such as Perl, .NET, Java, and others. Guice provides interceptors to intercept an application. For example, when a method is executed, you can add extra functionality before or after the method execution.

Important Classes

  1. Matcher - Matcher is an interface to either accept or reject a value. In Guice AOP, we need two matchers: one to define which classes participate, and another for the methods of those classes.

  2. MethodInterceptor - MethodInterceptors are executed when a matching method is called. They can inspect the call: the method, its arguments, and the receiving instance. We can perform cross-cutting logic and then delegate to the underlying method. Finally, we may inspect the return value or exception and return.

Example

创建名为 GuiceTester 的 Java 类。

Create a java class named GuiceTester.

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

编译并运行文件,用户可以看到以下输出。

Compile and run the file, you may see the following output.

Before checkSpelling
Inside checkSpelling.
After checkSpelling