`
carvin
  • 浏览: 212911 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[转]Google Guice 入门教程01 - 依赖注入

阅读更多

【前沿】本教程基于老菜鸟叮咚的教程,原文在此http://www.family168.com/tutorial/guice/html/。原文主要基于Google Guice 1.0版本的,本文基于Google Guice 2.0版本进行学习和讨论。

类依赖注入

所谓的绑定就是将一个接口绑定到具体的类中,这样客户端不用关心具体的实现,而只需要获取相应的接口完成其服务即可。

HelloWorld.java

 

1     public interface HelloWorld {
2 
3         String sayHello();
4     }
5 

然后是具体的实现,HelloWorldImpl.java

 

1     public class HelloWorldImpl implements HelloWorld {
2 
3         @Override
4         public String sayHello() {
5             return "Hello, world!";
6         }
7     }
8 

写一个测试例子看看,HelleWorldTest.java

 

 1     public class HelleWorldTest {
 2 
 3         @Test
 4         public void testSayHello() {
 5           Injector inj=  Guice.createInjector(new Module() {
 6                 @Override
 7                 public void configure(Binder binder) {
 8                     binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
 9                 }
10             });
11           HelloWorld hw = inj.getInstance(HelloWorld.class);
12           Assert.assertEquals(hw.sayHello(), "Hello, world!");
13         }
14     }
15 

这个例子非常简单,通俗的将就是将一个HelloWorldImpl的实例与HelloWorld关联起来,当想Guice获取一个HelloWorld实例的时候,Guice就返回一个HelloWorldImpl的实例,然后我们就可以调用HelloWorld服务的方法了。

问题(1)HelloWorld是单例的么?测试下。

 

1 HelloWorld hw = inj.getInstance(HelloWorld.class); 
2 Assert.assertEquals(hw.sayHello(), "Hello, world!");
3 HelloWorld hw2 = inj.getInstance(HelloWorld.class);
4 System.out.println(hw.hashCode()+"->"+hw2.hashCode());
5 Assert.assertEquals(hw.hashCode(), hw2.hashCode());

解答(1)测试结果告诉我们,HelloWorld不是单例的,每次都会返回一个新的实例。

问题(2)HelloWorld的实例是HelloWorldImpl么?可以强制转型么?

HelloWorld hw = inj.getInstance(HelloWorld.class);
System.out.println(hw.getClass().getName());

 

解答(2),结果输出cn.imxylz.study.guice.helloworld.HelloWorldImpl,看来确实只是返回了一个正常的实例,并没有做过多的转换和代理。

问题(3),如果绑定多个实现到同一个接口上会出现什么情况?

 

1 public class HelloWorldImplAgain implements HelloWorld {
2     @Override
3     public String sayHello() {
4         return "Hello world again.";
5     }
6 }

 

binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
binder.bind(HelloWorld.
class).to(HelloWorldImplAgain.class);

解答(3),很不幸,Guice目前看起来不允许多个实例绑定到同一个接口上了。

com.google.inject.CreationException: Guice creation errors:

1) A binding to cn.imxylz.study.guice.helloworld.HelloWorld was already configured at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28).
  at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:29)

问题(4),可以绑定一个实现类到实现类么?

1 Injector inj=  Guice.createInjector(new Module() {
2       @Override
3       public void configure(Binder binder) {
4           binder.bind(HelloWorldImpl.class).to(HelloWorldImpl.class);
5       }
6   });
7 HelloWorld hw = inj.getInstance(HelloWorldImpl.class);
8 System.out.println(hw.sayHello());

 

非常不幸,不可以自己绑定到自己。

1) Binding points to itself.
  at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28)

我们来看看bind的语法。

<T> AnnotatedBindingBuilder<T> bind(Class<T> type);

 

 

ScopedBindingBuilder to(Class<? extends T> implementation);

也就是说只能绑定一个类的子类到其本身。改造下,改用子类替代。

 

1     public class HelloWorldSubImpl extends HelloWorldImpl {
2 
3         @Override
4         public String sayHello() {
5             return "@HelloWorldSubImpl";
6         }
7     }
8 

 

1 Injector inj=  Guice.createInjector(new Module() {
2             @Override
3             public void configure(Binder binder) {
4                 binder.bind(HelloWorldImpl.class).to(HelloWorldSubImpl.class);
5             }
6         });
7       HelloWorldImpl hw = inj.getInstance(HelloWorldImpl.class);
8       System.out.println(hw.sayHello());

太好了,支持子类绑定,这样即使我们将一个实现类发布出去了(尽管不推荐这么做),我们在后期仍然有办法替换实现类。

使用bind有一个好处,由于JAVA 5以上的泛型在编译器就确定了,所以可以帮我们检测出绑定错误的问题,而这个在配置文件中是无法检测出来的。

这样看起来Module像是一个Map,根据一个Key获取其Value,非常简单的逻辑。

问题(5),可以绑定到我们自己构造出来的实例么?

解答(5)当然可以!看下面的例子。

 

1 Injector inj=  Guice.createInjector(new Module() {
2             @Override
3             public void configure(Binder binder) {
4                 binder.bind(HelloWorld.class).toInstance(new HelloWorldImpl());
5             }
6         });
7       HelloWorld hw = inj.getInstance(HelloWorld.class);
8       System.out.println(hw.sayHello());

问题(6),我不想自己提供逻辑来构造一个对象可以么?

解答(6),可以Guice提供了一个方式(Provider<T>),允许自己提供构造对象的方式。

 

 1 Injector inj=  Guice.createInjector(new Module() {
 2       @Override
 3       public void configure(Binder binder) {
 4           binder.bind(HelloWorld.class).toProvider(new Provider<HelloWorld>() {
 5               @Override
 6               public HelloWorld get() {
 7                   return new HelloWorldImpl();
 8               }
 9           });
10       }
11   });
12 HelloWorld hw = inj.getInstance(HelloWorld.class);
13 System.out.println(hw.sayHello());

问题(7),实现类可以不经过绑定就获取么?比如我想获取HelloWorldImpl的实例而不通过Module绑定么?

解答(7),可以,实际上Guice能够自动寻找实现类。

 

Injector inj=  Guice.createInjector();
HelloWorld hw 
= inj.getInstance(HelloWorldImpl.class);
System.out.println(hw.sayHello());

问题(8),可以使用注解方式完成注入么?不想手动关联实现类。

解答(8),好,Guice提供了注解的方式完成关联。我们需要在接口上指明此接口被哪个实现类关联了。

 

1     @ImplementedBy(HelloWorldImpl.class)
2     public interface HelloWorld {
3 
4         String sayHello();
5     }
6 

 

Injector inj=  Guice.createInjector();
HelloWorld hw 
= inj.getInstance(HelloWorld.class);
System.out.println(hw.sayHello());

 

事实上对于一个已经被注解的接口我们仍然可以使用Module来关联,这样获取的实例将是Module关联的实例,而不是@ImplementedBy注解关联的实例。这样仍然遵循一个原则,手动优于自动。

问题(9)再回头看问题(1)怎么绑定一个单例?

 1     Injector inj = Guice.createInjector(new Module() {
 2 
 3         @Override
 4         public void configure(Binder binder) {
 5             binder.bind(HelloWorld.class).to(HelloWorldImplAgain.class).in(Scopes.SINGLETON);
 6         }
 7     });
 8     HelloWorld hw = inj.getInstance(HelloWorld.class);
 9     HelloWorld hw2 = inj.getInstance(HelloWorld.class);
10     System.out.println(hw.hashCode() + "->" + hw2.hashCode());
11 

可以看到现在获取的实例已经是单例的,不再每次请求生成一个新的实例。事实上Guice提供两种Scope,com.google.inject.Scopes.SINGLETON和com.google.inject.Scopes.NO_SCOPE,所谓没有scope即是每次生成一个新的实例。

对于自动注入就非常简单了,只需要在实现类加一个Singleton注解即可。

1     @Singleton
2     public class HelloWorldImpl implements HelloWorld {
3 
4         @Override
5         public String sayHello() {
6             return "Hello, world!";
7         }
8     }
9

 

原文地址:http://ajava.org/course/open/17683.html

分享到:
评论

相关推荐

    guice入门教程helloworld篇

    在"Guice入门教程HelloWorld篇"中,我们将学习如何使用Guice来构建简单的Java应用程序。首先,我们需要理解Guice的核心概念——模块(Module)和绑定(Binding)。模块是Guice配置的核心,它定义了哪些类应该被实例...

    Guice教程(Google)

    #### 四、Guice入门 Guice通过使用`@Inject`注解来自动注入依赖项,这使得代码更简洁且易于理解。例如,如果有一个`UserService`类依赖于`UserRepository`,可以这样定义: ```java public class UserService { ...

    Struts2的第一个入门实例(三)--Struts2与Guice整合

    在本实例中,我们将深入探讨如何将Google的依赖注入框架Guice与Struts2整合,以实现更高效、更灵活的代码管理。 在Java Web开发中,依赖注入(DI)是一种设计模式,它可以帮助我们降低组件之间的耦合,使得测试和...

    khs-sherpa-guice:夏尔巴人的 Guice 注入集成

    khsSherpa 的 Google Guice 依赖注入集成。 此处链接到 khsSherpa 项目...[ ] 入门 要使其正常工作,请按照下列步骤操作: 添加 &lt;listener&gt;com.khs.guice.SherpaGuiceContextListener&lt;/listener&gt; 在 Sherpa ...

    shiro,guice集成

    而 Google 的 Guice 则是一个流行的依赖注入框架,它简化了对象的创建和管理过程。本文将详细介绍如何将 Apache Shiro 集成到基于 Guice 的应用中。 #### Apache Shiro 与 Guice 集成概述 自 Shiro 1.2 版本起,...

    Hello-Google-Guice:第一个Google Guice项目

    **Hello-Google-Guice: Google Guice 入门教程** Google Guice 是一个轻量级的依赖注入框架,主要用于简化 Java 应用程序的构建和管理。它通过自动管理和提供对象之间的依赖关系,帮助开发者编写更加简洁、可测试...

    Shiro全面教程

    - `shiro-guice-1.2.0.jar` 提供了与 Google Guice 依赖注入框架的集成。 - `shiro-spring-1.2.0.jar` 用于与 Spring 框架的集成。 通过这个全面教程,你不仅可以掌握 Shiro 的基础,还能深入了解其在实际项目中...

    api-start:球衣+guice+mybatis+gradle+liquibase 入门套件

    2. "Guice":Google Guice是一个轻量级的依赖注入框架,简化了Java对象的创建和管理,使得代码更加松耦合,更易于测试和维护。 3. "MyBatis":MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级...

    MyBatis核心教程

    在mybatis-guice中,可以轻松地通过Guice的依赖注入机制获取Mapper实例,简化了Mapper的使用流程。 #### 6. @Transactional注解 ##### 6.1 引言 mybatis-guice支持使用`@Transactional`注解来简化事务管理。 ###...

    Xtext手册-用于开发语言工具的框架

    - **依赖注入**:介绍如何在Xtext中使用Google Guice进行依赖注入。 - **模块API**:解释如何使用Guice的模块API来定义依赖关系。 - **获取注入器**:指导如何从Guice中获取注入器实例。 ##### 9. 运行时概念 - *...

    GWT完整教程,Word版

    这一部分还将深入讨论GWT的客户端数据管理,包括使用 Gin 和 Guice 进行依赖注入,以及使用GWT的 Place 和 History 模式来实现导航。另外,你将学习到如何利用GWT的Ext GWT(GXT)或SmartGWT等第三方库增强应用的...

    Spring_3.x企业应用开发实战 目录

    - **Google Guice**:Google 提供的一个轻量级 DI 框架。 - **Jdon Framework**:提供了一系列企业级应用开发工具。 - **1.12 小结** - **总结**:介绍了 Spring 框架的基本概念、新功能以及生态系统。 #### 第...

    GWT入门和进阶

    Gin是GWT上的轻量级依赖注入框架,基于Guice,它可以帮助管理复杂的组件依赖关系,简化代码结构。 **3. RequestFactory** RequestFactory是GWT提供的一种更加简洁的服务器通信方式,它提供了更面向对象的API,方便...

    Xtext Documentation

    这部分介绍了如何使用Xtext的配置组件,包括语言生成器和Google Guice的依赖注入。 #### 持续集成 介绍了如何使用Maven和Tycho进行Xtext语言的构建和集成。 #### 运行时概念 这部分阐述了Xtext运行时环境的细节...

    xtext基础入门说明资料

    为了更好地管理依赖关系,Xtext采用了Google Guice库。开发者可以通过定义模块来指定依赖注入的行为。 **4.2.2 获取注入器** 通过获取注入器,开发者可以访问到Xtext中的各种服务和组件。 #### 5. 运行时概念 **...

    how to use xtext

    Xtext支持通过Google Guice框架进行依赖注入,以实现组件之间的松耦合。 ### 六、运行时概念 #### 6.1 运行时设置 描述了Xtext运行时环境的初始化过程,包括ISetup接口的使用。 #### 6.2 Eclipse-Equinox中的...

    Selenium_Framework

    9. **Dependency Injection**:如 Spring 或 Guice 可用于管理和注入对象,提升代码的灵活性和可测试性。 通过以上组件和设计模式的组合,我们可以构建出强大而灵活的 Selenium 测试框架,满足不同项目的自动化测试...

Global site tag (gtag.js) - Google Analytics