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