- 谷歌指南
- Guice - 主页
- Guice - 概述
- Guice - 环境设置
- Guice - 首次申请
- 绑定示例
- Guice - 链接绑定
- Guice - 绑定注释
- Guice - @Named 绑定
- Guice - 常量绑定
- Guice - @Provides Annotation
- Guice - 提供者类
- Guice - 构造函数绑定
- Guice - 内置绑定
- Guice - 即时绑定
- 注射实例
- Guice - 构造函数注入
- Guice - 方法注入
- Guice - 现场注射
- Guice - 可选注射
- Guice - 按需注射
- 其他例子
- Guice - 范围
- Guice-AOP
- 有用的资源
- Guice - 快速指南
- Guice - 有用的资源
- Guice - 讨论
Google Guice - 快速指南
Google Guice - 概述
Guice 是一个开源的、基于 Java 的依赖注入框架。它是安静的轻量级,由 Google 积极开发/管理。
依赖注入
每个基于 Java 的应用程序都有一些对象,它们一起工作以呈现最终用户所看到的工作应用程序。在编写复杂的 Java 应用程序时,应用程序类应尽可能独立于其他 Java 类,以增加重用这些类并在单元测试时独立于其他类进行测试的可能性。依赖注入(有时称为连接)有助于将这些类粘合在一起,同时保持它们的独立性。
假设您有一个具有文本编辑器组件的应用程序,并且您想要提供拼写检查。你的标准代码看起来像这样 -
public class TextEditor { private SpellChecker spellChecker; public TextEditor() { spellChecker = new SpellChecker(); } }
我们在这里所做的是在文本编辑器和拼写检查器之间创建依赖关系。在控制反转场景中,我们会做这样的事情 -
public class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } }
在这里,文本编辑器不应该担心拼写检查器的实现。SpellChecker 将独立实现,并在 TextEditor 实例化时提供给 TextEditor。
使用 Guice 进行依赖注入(绑定)
依赖注入由 Guice 绑定控制。Guice 使用绑定将对象类型映射到其实际实现。这些绑定被定义为一个模块。模块是绑定的集合,如下所示:
public class TextEditorModule extends AbstractModule { @Override protected void configure() { /* * Bind SpellChecker binding to WinWordSpellChecker implementation * whenever spellChecker dependency is used. */ bind(SpellChecker.class).to(WinWordSpellChecker.class); } }
该模块是 Injector 的核心构建块,它是 Guice 的对象图构建器。第一步是创建一个注入器,然后我们可以使用注入器来获取对象。
public static void main(String[] args) { /* * Guice.createInjector() takes Modules, and returns a new Injector * instance. This method is to be called once during application startup. */ Injector injector = Guice.createInjector(new TextEditorModule()); /* * Build object using injector */ TextEditor textEditor = injector.getInstance(TextEditor.class); }
在上面的示例中,TextEditor 类对象图是由 Guice 构建的,该图包含 TextEditor 对象及其依赖项 WinWordSpellChecker 对象。
Google Guice - 环境设置
本地环境设置
如果您仍然愿意为 Java 编程语言设置环境,那么本节将指导您如何在计算机上下载和设置 Java。请按照以下步骤设置环境。
Java SE 可以通过下载 Java链接免费获得。因此,您可以根据您的操作系统下载一个版本。
按照说明下载 Java 并运行 .exe以在您的计算机上安装 Java。在计算机上安装 Java 后,您需要设置环境变量以指向正确的安装目录 -
设置 Windows 2000/XP 的路径
我们假设您已将 Java 安装在c:\Program Files\java\jdk目录中 -
右键单击“我的电脑”并选择“属性”。
单击“高级”选项卡下的“环境变量”按钮。
现在,更改“Path”变量,使其也包含 Java 可执行文件的路径。例如,如果路径当前设置为“C:\WINDOWS\SYSTEM32”,则将路径更改为“C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin”。
设置 Windows 95/98/ME 的路径
我们假设您已将 Java 安装在c:\Program Files\java\jdk目录中 -
编辑 'C:\autoexec.bat' 文件并在末尾添加以下行 - 'SET PATH=%PATH%;C:\Program Files\java\jdk\bin'
设置 Linux、UNIX、Solaris、FreeBSD 的路径
应将环境变量 PATH 设置为指向 Java 二进制文件的安装位置。如果您在执行此操作时遇到问题,请参阅您的 shell 文档。
例如,如果您使用 bash 作为 shell,那么您可以将以下行添加到“.bashrc:export PATH=/path/to/java:$PATH”的末尾
流行的 Java 编辑器
要编写 Java 程序,您需要一个文本编辑器。市场上有许多复杂的 IDE。但现在,您可以考虑以下其中一项 -
记事本- 在 Windows 计算机上,您可以使用任何简单的文本编辑器,例如记事本(本教程推荐)、TextPad。
Netbeans - 它是一个开源且免费的 Java IDE,可以从https://www.netbeans.org/index.html下载。
Eclipse - 它也是由 eclipse 开源社区开发的 Java IDE,可以从https://www.eclipse.org/下载。
谷歌Guice环境
下载最新版本的 Google Guice 和相关 jar 文件。
在编写本教程时,我们已将它们复制到 C:\>Google 文件夹中。
操作系统 | 档案名称 |
---|---|
Windows | guice-4.1.0.jar;aopalliance-1.0.jar;guava-16.0.1.jar;javax.inject-1.jar |
Linux | guice-4.1.0.jar;aopalliance-1.0.jar;guava-16.0.1.jar;javax.inject-1.jar |
苹果 | guice-4.1.0.jar;aopalliance-1.0.jar;guava-16.0.1.jar;javax.inject-1.jar |
设置 CLASSPATH 变量
设置CLASSPATH环境变量以指向 Guice jar 位置。假设您已将 Guice 和相关 jar 存储在各种操作系统上的 Google 文件夹中,如下所示。
操作系统 | 输出 |
---|---|
Windows | 将环境变量 CLASSPATH 设置为 %CLASSPATH%;C:\Google\guice-4.1.0.jar;C:\Google\aopalliance-1.0.jar;C:\Google\guava-16.0.1.jar;C:\ Google\javax.inject-1.jar;.; |
Linux | 导出 CLASSPATH=$CLASSPATH:Google/guice-4.1.0.jar:Google/aopalliance-1.0.jar:Google/guava-16.0.1.jar:Google/javax.inject-1.jar:。 |
苹果 | 导出 CLASSPATH=$CLASSPATH:Google/guice-4.1.0.jar:Google/aopalliance-1.0.jar:Google/guava-16.0.1.jar:Google/javax.inject-1.jar:。 |
Google Guice - 第一个应用程序
让我们创建一个基于控制台的示例应用程序,我们将在其中逐步演示使用 Guice 绑定机制的依赖注入。
第1步:创建接口
//spell checker interface interface SpellChecker { public void checkSpelling(); }
第 2 步:创建实施
//spell checker implementation class SpellCheckerImpl implements SpellChecker { @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } }
第 3 步:创建绑定模块
//Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); } }
第四步:创建具有依赖关系的类
class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } }
第5步:创建注入器
Injector injector = Guice.createInjector(new TextEditorModule());
步骤6:获取满足依赖关系的对象。
TextEditor editor = injector.getInstance(TextEditor.class);
第7步:使用该对象。
editor.makeSpellCheck();
完整示例
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); } } //spell checker interface interface SpellChecker { public void checkSpelling(); } //spell checker implementation class SpellCheckerImpl implements SpellChecker { @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling.
Google Guice - 链接绑定
在链接绑定中,Guice 将类型映射到其实现。在下面的示例中,我们将 SpellChecker 接口与其实现 SpellCheckerImpl 进行了映射。
bind(SpellChecker.class).to(SpellCheckerImpl.class);
我们还可以将具体类映射到它的子类。请参阅下面的示例:
bind(SpellCheckerImpl.class).to(WinWordSpellCheckerImpl.class);
在这里我们已经链接了绑定。让我们看看完整示例的结果。
完整示例
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); bind(SpellCheckerImpl.class).to(WinWordSpellCheckerImpl.class); } } //spell checker interface interface SpellChecker { public void checkSpelling(); } //spell checker implementation class SpellCheckerImpl implements SpellChecker { @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } } //subclass of SpellCheckerImpl class WinWordSpellCheckerImpl extends SpellCheckerImpl{ @Override public void checkSpelling() { System.out.println("Inside WinWordSpellCheckerImpl.checkSpelling." ); } }
输出
编译并运行该文件,您将看到以下输出。
Inside WinWordSpellCheckerImpl.checkSpelling.
Google Guice - 绑定注释
因为我们可以将类型与其实现绑定。如果我们想要映射具有多个实现的类型,我们也可以创建自定义注释。请参阅下面的示例来理解这个概念。
创建绑定注释
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME) @interface WinWord {}
@BindingAnnotation - 将注释标记为绑定注释。
@Target - 标记注释的适用性。
@Retention - 将注释的可用性标记为运行时。
使用绑定注释进行映射
bind(SpellChecker.class).annotatedWith(WinWord.class).to(WinWordSpellCheckerImpl.class);
使用绑定注释注入
@Inject public TextEditor(@WinWord SpellChecker spellChecker) { this.spellChecker = spellChecker; }
完整示例
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import java.lang.annotation.Target; import com.google.inject.AbstractModule; import com.google.inject.BindingAnnotation; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; @BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME) @interface WinWord {} public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor(@WinWord SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).annotatedWith(WinWord.class) .to(WinWordSpellCheckerImpl.class); } } //spell checker interface interface SpellChecker { public void checkSpelling(); } //spell checker implementation class SpellCheckerImpl implements SpellChecker { @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } } //subclass of SpellCheckerImpl class WinWordSpellCheckerImpl extends SpellCheckerImpl{ @Override public void checkSpelling() { System.out.println("Inside WinWordSpellCheckerImpl.checkSpelling." ); } }
输出
编译并运行该文件,您将看到以下输出。
Inside WinWordSpellCheckerImpl.checkSpelling.
Google Guice - 命名绑定
Guice 还提供了另一种方法来映射绑定,而无需创建自定义注释。它允许使用 @Named 注释。
使用命名注释进行映射
bind(SpellChecker.class).annotatedWith(Names.named("OpenOffice")).to(OpenOfficeWordSpellCheckerImpl.class);
使用@Named注解注入
@Inject public TextEditor(@Named("OpenOffice") SpellChecker spellChecker) { this.spellChecker = spellChecker; }
完整示例
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; import com.google.inject.name.Names; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor(@Named("OpenOffice") SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).annotatedWith(Names.named("OpenOffice")) .to(OpenOfficeWordSpellCheckerImpl.class); } } //spell checker interface interface SpellChecker { public void checkSpelling(); } //spell checker implementation class SpellCheckerImpl implements SpellChecker { @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } } //subclass of SpellCheckerImpl class OpenOfficeWordSpellCheckerImpl extends SpellCheckerImpl{ @Override public void checkSpelling() { System.out.println("Inside OpenOfficeWordSpellCheckerImpl.checkSpelling." ); } }
输出
编译并运行该文件,您将看到以下输出。
Inside OpenOfficeWordSpellCheckerImpl.checkSpelling.
Google Guice - 常量绑定
Guice 提供了一种创建与值对象或常量的绑定的方法。考虑我们要配置 JDBC url 的情况。
使用@Named注解注入
@Inject public void connectDatabase(@Named("JBDC") String dbUrl) { //... }
这可以使用 toInstance() 方法来实现。
bind(String.class).annotatedWith(Names.named("JBDC")).toInstance("jdbc:mysql://localhost:5326/emp");
完整示例
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; import com.google.inject.name.Names; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeConnection(); } } class TextEditor { private String dbUrl; @Inject public TextEditor(@Named("JDBC") String dbUrl) { this.dbUrl = dbUrl; } public void makeConnection(){ System.out.println(dbUrl); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(String.class) .annotatedWith(Names.named("JDBC")) .toInstance("jdbc:mysql://localhost:5326/emp"); } }
输出
编译并运行该文件,您将看到以下输出。
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; }
该方法是绑定模块的一部分,并提供要映射的复杂对象。请参阅下面的完整示例。
完整示例
创建一个名为 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); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp user 100
Google Guice - 提供商界面
随着 @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);
请参阅下面的完整示例。
完整示例
创建一个名为 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; } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp user 100
Google Guice - 构造函数绑定
Guice 提供了一种使用 toConstructor() 方法创建与对象的特定构造函数的绑定的方法。
@Override protected void configure() { try { bind(SpellChecker.class) .toConstructor(SpellCheckerImpl.class.getConstructor(String.class)); } catch (NoSuchMethodException | SecurityException e) { System.out.println("Required constructor missing"); } }
请参阅下面的完整示例。
完整示例
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; import com.google.inject.name.Names; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor( SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { try { bind(SpellChecker.class) .toConstructor(SpellCheckerImpl.class.getConstructor(String.class)); } catch (NoSuchMethodException | SecurityException e) { System.out.println("Required constructor missing"); } bind(String.class) .annotatedWith(Names.named("JDBC")) .toInstance("jdbc:mysql://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); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp
Google Guice - 内置绑定
Guice 为java.util.logging.Logger类提供内置绑定。Logger 的名称会自动设置为注入 Logger 的类的名称。请参阅下面的示例。
例子
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import java.util.logging.Logger; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private Logger logger; @Inject public TextEditor( Logger logger) { this.logger = logger; } public void makeSpellCheck(){ logger.info("In TextEditor.makeSpellCheck() method"); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { } }
输出
编译并运行该文件,您将看到以下输出。
Dec 20, 2017 12:51:05 PM TextEditor makeSpellCheck INFO: In TextEditor.makeSpellCheck() method
Google Guice - 即时绑定
由于绑定是在 Binding Module 中定义的,Guice 在需要注入依赖项时就会使用它们。如果绑定不存在,它可以尝试创建即时绑定。绑定模块中存在的绑定称为显式绑定,并且具有更高的优先级,而即时绑定称为隐式绑定。如果两种类型的绑定都存在,则考虑使用显式绑定进行映射。
以下是三种类型的即时绑定的示例。
装订类型 | 描述 |
---|---|
可注入构造函数 | 非私有、无参构造函数有资格进行即时绑定。另一种方法是使用 @Inject 注解来注解构造函数。 |
@ImplementatedBy注释 | @ImplementatedBy 注释告诉我们有关实现类的信息。在这种情况下,绑定模块中不需要绑定。 |
@ProvidedBy注解 | @ProvidedBy注释告诉有关实现类的提供者的信息。在这种情况下,绑定模块中不需要绑定。 |
Guice - 可注入构造函数
非私有、无参构造函数有资格进行即时绑定。另一种方法是使用 @Inject 注解来注解构造函数。参见示例:
例子
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; import com.google.inject.name.Names; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor( SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); bind(String.class) .annotatedWith(Names.named("JDBC")) .toInstance("jdbc:mysql://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); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp
Guice - @ImplementatedBy 注释
@ImplementatedBy 注释告诉我们有关实现类的信息。在这种情况下,绑定模块中不需要绑定。参见示例:
例子
创建一个名为 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); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp
Google Guice - @ProvidedBy 注解
@ProvidedBy注释告诉有关实现类的提供者的信息。在这种情况下,绑定模块中不需要绑定。参见示例:
例子
创建一个名为 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; } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp user 100
Google Guice - 构造函数注入
注入是将依赖项注入到对象中的过程。构造函数注入很常见。在此过程中,依赖项作为参数注入到构造函数中。请参阅下面的示例。
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); } } //spell checker interface interface SpellChecker { public void checkSpelling(); } //spell checker implementation class SpellCheckerImpl implements SpellChecker { @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling.
Google Guice - 方法注入
注入是将依赖项注入到对象中的过程。方法注入用于将值对象设置为对象的依赖项。请参阅下面的示例。
例子
创建一个名为 GuiceTester 的 java 类。
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.ImplementedBy; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; import com.google.inject.name.Names; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor( SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(String.class) .annotatedWith(Names.named("JDBC")) .toInstance("jdbc:mysql://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); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp
Google Guice - 现场注入
注入是将依赖项注入到对象中的过程。字段注入用于将值对象设置为对对象字段的依赖。请参阅下面的示例。
例子
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.ImplementedBy; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; import com.google.inject.name.Names; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor( SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(String.class) .annotatedWith(Names.named("JDBC")) .toInstance("jdbc:mysql://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); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp
Google Guice - 可选注入
注入是将依赖项注入到对象中的过程。可选注入意味着注入依赖项(如果存在)。方法和字段注入可以选择性地依赖,并且如果不存在依赖项,则应该具有一些默认值。请参阅下面的示例。
例子
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.ImplementedBy; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public TextEditor( SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() {} } @ImplementedBy(SpellCheckerImpl.class) interface SpellChecker { public void checkSpelling(); } //spell checker implementation class SpellCheckerImpl implements SpellChecker { private String dbUrl = "jdbc:mysql://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); } }
输出
编译并运行该文件,您将看到以下输出。
Inside checkSpelling. jdbc:mysql://localhost:5326/emp
Google Guice - 按需注入
注入是将依赖项注入到对象中的过程。方法和字段注入可用于使用injector.injectMembers()方法使用现有对象进行初始化。请参阅下面的示例。
例子
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.ImplementedBy; import com.google.inject.Inject; import com.google.inject.Injector; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); SpellChecker spellChecker = new SpellCheckerImpl(); injector.injectMembers(spellChecker); TextEditor editor = injector.getInstance(TextEditor.class); editor.makeSpellCheck(); } } class TextEditor { private SpellChecker spellChecker; @Inject public void setSpellChecker(SpellChecker spellChecker){ this.spellChecker = spellChecker; } public TextEditor() { } public void makeSpellCheck(){ spellChecker.checkSpelling(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { } } @ImplementedBy(SpellCheckerImpl.class) interface SpellChecker { public void checkSpelling(); } //spell checker implementation class SpellCheckerImpl implements SpellChecker { public SpellCheckerImpl(){} @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } }
编译并运行该文件,您将看到以下输出。
Inside checkSpelling.
Google Guice - 范围
Guice 每次提供一个值作为其默认Behave时都会返回一个新实例。它可以通过范围进行配置。以下是 Guice 支持的范围:
@Singleton - 应用程序生命周期的单个实例。@Singleton 对象需要是线程安全的。
@SessionScoped - Web 应用程序特定会话的单个实例。@SessionScoped 对象需要是线程安全的。
@RequestScoped - Web 应用程序的特定请求的单个实例。@RequestScoped 对象不需要是线程安全的。
应用范围的方式。
以下是应用范围的方法。
在班级层面
@Singleton class SpellCheckerImpl implements SpellChecker { public SpellCheckerImpl(){} @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } }
在配置级别
bind(SpellChecker.class).to(SpellCheckerImpl.class).in(Singleton.class);
在方法级别
@Provides @Singleton public SpellChecker provideSpellChecker(){ String dbUrl = "jdbc:mysql://localhost:5326/emp"; String user = "user"; int timeout = 100; SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout); return SpellChecker; }
例子
让我们看看类级别的范围的实际效果。
带@Singleton注释的结果
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); SpellChecker spellChecker = new SpellCheckerImpl(); injector.injectMembers(spellChecker); TextEditor editor = injector.getInstance(TextEditor.class); System.out.println(editor.getSpellCheckerId()); TextEditor editor1 = injector.getInstance(TextEditor.class); System.out.println(editor1.getSpellCheckerId()); } } class TextEditor { private SpellChecker spellChecker; @Inject public void setSpellChecker(SpellChecker spellChecker){ this.spellChecker = spellChecker; } public TextEditor() { } public void makeSpellCheck(){ spellChecker.checkSpelling(); } public double getSpellCheckerId(){ return spellChecker.getId(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); } } interface SpellChecker { public double getId(); public void checkSpelling(); } @Singleton class SpellCheckerImpl implements SpellChecker { double id; public SpellCheckerImpl(){ id = Math.random(); } @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } @Override public double getId() { return id; } }
编译并运行该文件,您可能会看到以下输出。
0.3055839187063575 0.3055839187063575
没有@Singleton注释的结果
创建一个名为 GuiceTester 的 java 类。
GuiceTester.java
import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; public class GuiceTester { public static void main(String[] args) { Injector injector = Guice.createInjector(new TextEditorModule()); SpellChecker spellChecker = new SpellCheckerImpl(); injector.injectMembers(spellChecker); TextEditor editor = injector.getInstance(TextEditor.class); System.out.println(editor.getSpellCheckerId()); TextEditor editor1 = injector.getInstance(TextEditor.class); System.out.println(editor1.getSpellCheckerId()); } } class TextEditor { private SpellChecker spellChecker; @Inject public void setSpellChecker(SpellChecker spellChecker){ this.spellChecker = spellChecker; } public TextEditor() { } public void makeSpellCheck(){ spellChecker.checkSpelling(); } public double getSpellCheckerId(){ return spellChecker.getId(); } } //Binding Module class TextEditorModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); } } interface SpellChecker { public double getId(); public void checkSpelling(); } class SpellCheckerImpl implements SpellChecker { double id; public SpellCheckerImpl(){ id = Math.random(); } @Override public void checkSpelling() { System.out.println("Inside checkSpelling." ); } @Override public double getId() { return id; } }
编译并运行该文件,您可能会看到以下输出。
0.556007079571739 0.22095011760351602
谷歌Guice-AOP
AOP,面向方面的编程需要将程序逻辑分解为不同的部分,称为所谓的关注点。跨越应用程序多个点的功能称为横切关注点,这些横切关注点在概念上与应用程序的业务逻辑是分开的。日志记录、审计、声明性事务、安全性、缓存等方面有各种常见的好例子。
OOP 中模块化的关键单元是类,而 AOP 中模块化的单元是方面。依赖注入可以帮助您将应用程序对象彼此解耦,AOP 可以帮助您将横切关注点与其影响的对象解耦。AOP 就像 Perl、.NET、Java 等编程语言中的触发器。Guice 提供拦截器来拦截应用程序。例如,当执行方法时,您可以在方法执行之前或之后添加额外的功能。
重要课程
Matcher - Matcher 是接受或拒绝值的接口。在 Guice AOP 中,我们需要两个匹配器:一个用于定义哪些类参与,另一个用于这些类的方法。
MethodInterceptor - MethodInterceptor 在调用匹配方法时执行。他们可以检查调用:方法、其参数和接收实例。我们可以执行横切逻辑,然后委托给底层方法。最后,我们可以检查返回值或异常并返回。
例子
创建一个名为 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