参考链接:http://www.cnblogs.com/xd502djj/archive/2012/06/25/2561414.html

http://code.google.com/p/google-guice/

Google公司的Bob lee开发的轻量级IoC容器,其特点是:

1、速度快,号称是spring的100倍速度 
2、无配置文件,实用JDK5.0的annotation描述组件依赖,简单,而且有编译器检查和重构支持 
3、简单,代码量很少

http://code.google.com/p/google-guice/wiki/SpringComparison

这是Google guice和spring IoC容器的对比

另外xwork2.0已经集成了Google guice容器了。

http://docs.google.com/Doc?id=dd2fhx4z_5df5hw8

这是Google guice的快速入门文档,用起来挺简单的。

Google Guice范例解说之使用入门
本文通过范例简单地介绍Google Guice的使用,通过下面的范例我们可以知道,Google Guice的使用非常简单。

  Google Guice需要使用JDK1.5以上java环境。

  下载Google Guice之后,

  有以下几个文件:

  aopalliance.jar

  guice-1.0.jar

  guice-servlet-1.0.jar

  guice-spring-1.0.jar

  guice-struts2-plugin-1.0.jar

  本例只使用到guice-1.0.jar文件,将其加入到class path中。

  下面简单地介绍范例:

  范例1:使用com.google.inject.Module接口实现类

文件名 说明

文件名 说明
HelloGuice.java 业务逻辑接口定义文件
HelloGuiceImpl.java 业务逻辑接口实现文件
HelloGuiceModule.java 该文件必须实现com.google.inject.Module接口
TestGuice.java 测试文件

HelloGuice.java
  
package com.test.guice;
  
public interface HelloGuice {
  public void sayHello();
}
  
HelloGuiceImpl.java
  
package com.test.guice;
  
public class HelloGuiceImpl implements HelloGuice {
  
  public void sayHello() {
    System.out.println("Hello Guice!");
  }
}
  
HelloGuiceModule.java

package com.test.guice;
  
import com.google.inject.Binder;
import com.google.inject.Module;
  
public class HelloGuiceModule implements Module {
  
  public void configure(Binder binder) {
    binder.bind(HelloGuice.class).to(HelloGuiceImpl.class);
  }
  
}
  
TestGuice.java
package com.test.guice;
  
import junit.framework.TestCase;
  
import com.google.inject.Guice;
import com.google.inject.Injector;
  
public class TestGuice extends TestCase {
  public void testHelloGuice() {
    Injector injector = Guice.createInjector(new HelloGuiceModule());
    
    HelloGuice helloGuice = injector.getInstance(HelloGuice.class);
    helloGuice.sayHello();
  }
}

  运行TestGuice,打印出:

  Hello Guice!

  范例2:使用Java Annotation

  我们也可以直接为HelloGuice加上@ImplementedBy注释,而省略掉对com.google.inject.Module的实现。

HelloGuice.java
package com.test.guice;
  
import com.google.inject.ImplementedBy;
  
@ImplementedBy(HelloGuiceImpl.class)
public interface HelloGuice {
  public void sayHello();
}
  
TestGuice.java 
package com.test.guice;
  
import junit.framework.TestCase;
  
import com.google.inject.Guice;
import com.google.inject.Injector;
  
public class TestGuice extends TestCase {
  public void testHelloGuice() {
    //Injector injector = Guice.createInjector(new HelloGuiceModule());
    
    Injector injector = Guice.createInjector();
    HelloGuice helloGuice = injector.getInstance(HelloGuice.class);
    helloGuice.sayHello();
  }
}

  HelloGuiceModule.java不再需要。其余的文件内容不变。

  运行TestGuice,打印出:

  Hello Guice!

摘自 :http://hi.baidu.com/changzhiwin/blog/item/1e8251861feb553466096e36.html

1. 依赖注入

1.1 类依赖注入

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

HelloWorld.java

1     public interface HelloWorld {

3         String sayHello();
4     }

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

1     public class HelloWorldImpl implements HelloWorld {

3         @Override
4         public String sayHello() {
5             return "Hello, world!";
6         }
7     }

写一个测试例子看看,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 {

3         @Override
4         public String sayHello() {
5             return "@HelloWorldSubImpl";
6         }
7     }
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 {

4         String sayHello();
5     }
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 {

4         @Override
5         public String sayHello() {
6             return "Hello, world!";
7         }
8     }
9

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

1.2 属性注入(Field Inject)

1.2.1 基本属性注入

首先来看一个例子。Service.java

1 @ImplementedBy(ServiceImpl.class)
2 public interface Service {
3     void execute();
4 }

ServiceImpl.java

1 public class ServiceImpl implements Service {
2     @Override
3     public void execute() {
4         System.out.println("This is made by imxylz (www.imxylz.cn).");
5     }
6 }

FieldInjectDemo.java

 1 /** a demo with Field inject
 2  * @author xylz (www.imxylz.cn)
 3  * @version $Rev: 71 $
 4  */
 5 public class FieldInjectDemo {
 6     @Inject
 7     private Service servcie;
 8     public Service getServcie() {
 9         return servcie;
10     }
11     public static void main(String[] args) {
12         FieldInjectDemo demo = Guice.createInjector().getInstance(FieldInjectDemo.class);
13         demo.getServcie().execute();
14     }
15 }

这个例子比较简单。具体来说就是将接口Service通过@Inject注解注入到FieldInjectDemo类中,然后再FieldInjectDemo类中使用此服务而已。当然Service服务已经通过@ImplementedBy注解关联到ServiceImpl 类中,每次生成一个新的实例(非单例)。注意,这里FieldInjectDemo类没有通过Module等关联到Guice中,具体可以查看《》。

意料之中得到了我们期待的结果。

同样,我们通过问答的方式来加深理解(注意,入门教程我们只是强调怎么使用,至于原理和底层的思想我们放到高级教程中再谈)。

问题(1):可以自己构造FieldInjectDemo 对象而不通过Guice么?

 1 /** field inject demo2
 2  * @author xylz (www.imxylz.cn)
 3  * @version $Rev: 73 $
 4  */
 5 public class FieldInjectDemo2 {
 6     @Inject
 7     private Service servcie;
 8     public Service getServcie() {
 9         return servcie;
10     }
11     public static void main(String[] args) {
12         FieldInjectDemo2 fd = new FieldInjectDemo2();
13         fd.getServcie().execute();
14     }
15 }

就像上面的例子中一样,然后运行下看看?非常不幸,我们得到了一个谁都不喜欢的结果。

Exception in thread "main" java.lang.NullPointerException
    at cn.imxylz.study.guice.inject.FieldInjectDemo2.main(FieldInjectDemo2.java:22)

很显然,由于FieldInjectDemo2不属于Guice容器(暂且称为容器吧)托管,这样Service服务没有机会被注入到FieldInjectDemo2类中。

问题(2):可以注入静态属性么?

看下面的代码。

 1 public class FieldInjectDemo2 {
 2     @Inject
 3     private static Service servcie;
 4     public static Service getServcie() {
 5         return servcie;
 6     }
 7     public static void main(String[] args) {
 8         FieldInjectDemo2 fd = Guice.createInjector().getInstance(FieldInjectDemo2.class);
 9         FieldInjectDemo2.getServcie().execute();
10     }
11 }

很不幸!运行结果告诉我们Guice看起来还不支持静态字段注入。

好了,上面两个问题我们暂且放下,我们继续学习其它注入功能。

1.2.2 构造函数注入(Constructor Inject)

继续看例子。例子是说明问题的很好方式。

 1     /**
 2      * $Id: ConstructorInjectDemo.java 75 2009-12-23 14:22:35Z xylz $
 3      * xylz study project (www.imxylz.cn)
 4      */
 5     package cn.imxylz.study.guice.inject;
 6 
 7     import com.google.inject.Guice;
 8     import com.google.inject.Inject;
 9 
10     /** a demo with constructor inject
11      * @author xylz (www.imxylz.cn)
12      * @version $Rev: 75 $
13      */
14     public class ConstructorInjectDemo {
15 
16         private Service service;
17         @Inject
18         public ConstructorInjectDemo(Service service) {
19             this.service=service;
20         }
21         public Service getService() {
22             return service;
23         }
24         public static void main(String[] args) {
25             ConstructorInjectDemo cid = Guice.createInjector().getInstance(ConstructorInjectDemo.class);
26             cid.getService().execute();
27         }
28 
29     }
30 
31 

我们在构造函数上添加@Inject来达到自动注入的目的。构造函数注入的好处是可以保证只有一个地方来完成属性注入,这样可以确保在构造函数中完成一些初始化工作(尽管不推荐这么做)。当然构造函数注入的缺点是类的实例化与参数绑定了,限制了实例化类的方式。

问题(3):构造函数中可以自动注入多个参数么?

 1     public class ConstructorInjectDemo {
 2 
 3         private Service service;
 4         private HelloWorld helloWorld;
 5         @Inject
 6         public ConstructorInjectDemo(Service service,HelloWorld helloWorld) {
 7             this.service=service;
 8             this.helloWorld=helloWorld;
 9         }
10         public Service getService() {
11             return service;
12         }
13         public HelloWorld getHelloWorld() {
14             return helloWorld;
15         }
16         public static void main(String[] args) {
17             ConstructorInjectDemo cid = Guice.createInjector().getInstance(ConstructorInjectDemo.class);
18             cid.getService().execute();
19             System.out.println(cid.getHelloWorld().sayHello());
20         }
21     }
22 
23 

非常完美的支持了多参数构造函数注入。当然了没有必要写多个@Inject,而且写了的话不能通过编译。

1.2.3 Setter注入(Setter Method Inject)

有了上面的基础我们再来看Setter注入就非常简单了,只不过在setter方法上增加一个@Inject注解而已。

 1     public class SetterInjectDemo {
 2 
 3         private Service service;
 4 
 5         @Inject
 6         public void setService(Service service) {
 7             this.service = service;
 8         }
 9 
10         public Service getService() {
11             return service;
12         }
13 
14         public static void main(String[] args) {
15             SetterInjectDemo sid = Guice.createInjector().getInstance(SetterInjectDemo.class);
16             sid.getService().execute();
17         }
18 
19     }
20 
21 

好了我们再回头看问题2的静态注入(static inject)。下面的例子演示了如何注入一个静态的字段。

 1     /** a demo for static field inject
 2      * @author xylz (www.imxylz.cn)
 3      * @version $Rev: 78 $
 4      */
 5     public class StaticFieldInjectDemo {
 6 
 7         @Inject
 8         private static Service service;
 9 
10         public static void main(String[] args) {
11             Guice.createInjector(new Module() {
12                 @Override
13                 public void configure(Binder binder) {
14                     binder.requestStaticInjection(StaticFieldInjectDemo.class);
15                 }
16             });
17             StaticFieldInjectDemo.service.execute();
18         }
19     }
20 
21 

非常棒!上面我们并没有使用Guice获取一个StaticFieldInjectDemo实例(废话),实际上static字段(属性)是类相关的,因此我们需要请求静态注入服务。但是一个好处是在外面看起来我们的服务没有Guice绑定,甚至client不知道(或者不关心)服务的注入过程。

再回到问题(1),参考上面静态注入的过程,我们可以使用下面的方式来注入实例变量的属性。

 1     public class InstanceFieldInjectDemo {
 2 
 3         @Inject
 4         private Service service;
 5         public static void main(String[] args) {
 6            final InstanceFieldInjectDemo ifid = new InstanceFieldInjectDemo();
 7             Guice.createInjector(new Module() {
 8                 @Override
 9                 public void configure(Binder binder) {
10                     binder.requestInjection(ifid);
11                 }
12             });
13             ifid.service.execute();
14         }
15     }
16 
17 

实际上这里有一种简便的方法来注入字段,实际上此方法也支持Setter注入。

 1     public class InstanceFieldInjectDemo {
 2 
 3         @Inject
 4         private Service service;
 5         public static void main(String[] args) {
 6             InstanceFieldInjectDemo ifid = new InstanceFieldInjectDemo();
 7             Guice.createInjector().injectMembers(ifid);
 8             ifid.service.execute();
 9         }
10     }
11 
12 

好了既然是入门教程,我们就不讨论更深层次的东西了。

转自 http://www.blogjava.net/xylz/archive/2009/xylz/archive/2009/12/23/307092.html

 
 

Guice入门的更多相关文章

  1. guice框架的入门使用

    guice框架是一种类似于spring的ioc容器的一种框架,使用简单,比較轻量级的一个框架,速度极快,灵活性极强,如今就先来写几个guice的程序. 在这里我就不给出guice的jar包,这些都能够 ...

  2. java轻量级IOC框架Guice

    Google-Guice入门介绍(较为清晰的说明了流程):http://blog.csdn.net/derekjiang/article/details/7231490 使用Guice,需要添加第三方 ...

  3. MyBatis入门学习

    所需要jar包:mybatis-3.x.x.jar .如果需要和spring整合,还需要加入相关的包 1:看项目目录 红颜色不要关心 2:按照步骤: 1:加入jar包 2:创建数据源(configur ...

  4. guice的基本使用(一)

    guice是google一个轻量级的DI注入框架,现在比较强大了,也与目前流行的struts2.jpa等都有集成了. 先看一个例子: package com.ming.user.test; publi ...

  5. Google Guice学习

    学习动力:公司项目使用 官方文档:https://github.com/google/guice/wiki/Motivation 学习阶段:入门 主要部份: 简介 Bindings方式 Scopes设 ...

  6. 新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析

    1.引言 Netty 是一个广受欢迎的异步事件驱动的Java开源网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件 ...

  7. Spring.NET依赖注入框架学习--入门

    Spring.NET依赖注入框架学习--入门 在学些Spring.net框架之前,有必要先脑补一点知识,比如什么是依赖注入?IOC又是什么?控制反转又是什么意思?它们与Spring.net又有什么关系 ...

  8. Google-Guice入门介绍

    原地址:http://blog.csdn.net/derekjiang/article/details/7231490 一. 概述 Guice是一个轻量级的DI框架.本文对Guice的基本用法作以介绍 ...

  9. Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门

    本章将涵盖以下话题: ž  MyBatis是什么? ž  为什么选择MyBatis? ž  MyBatis安装配置 ž  域模型样例 1.1 MyBatis是什么 MyBatis是一个简化和实现了Ja ...

随机推荐

  1. 【LeetCode】064. Minimum Path Sum

    题目: Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right w ...

  2. Python 静态方法和类方法的区别

    python staticmethod and classmethod Though classmethod and staticmethod are quite similar, there’s a ...

  3. The current .NET SDK does not support targeting .NET Core 2.2

    The current .NET SDK does not support targeting .NET Core 2.2 1. 奇怪的错误 最近遇到了一件奇怪的事, The current .NET ...

  4. 2011年浙大:Twin Prime Conjecture

    Twin Prime Conjecture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  5. JavaScript代码放在HTML代码不同位置的差别

    通常情况下,JavaScript 代码是和 HTML 代码一起使用的,可以将 JavaScript 代码放置在 HTML 文档的任何地方.但放置的地方,会对 JavaScript 代码的正常执行会有一 ...

  6. 第一课、OpenGL绘制直线等等

    第一课.OpenGL绘制直线等等 分类: [开发技术]OpenGL 2012-01-18 14:59 5217人阅读 评论(0) 收藏 举报 buffer图形c // //  main.c //  o ...

  7. CentOS软件包管理

    rpm安装包管理 指令 说明 rpm -i XX.rpm 安装XX.rpm软件包 rpm -qa XX 查看XX软件包安装的所有文件 rpm -e XX 卸载XX软件包 yum管理软件 指令 说明 y ...

  8. npm ERR! Cannot read property 'match' of undefined 错误处理

    跟往常一样运行npm install 的时候,突然报错.错误情况如下: npm ERR! Cannot read property 'match' of undefined npm ERR! A co ...

  9. 用matplotlib画线

    1:matplotlib基础 Matplotlib 是一个 Python 的 2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形[1] . 通过 Matplotlib,开发者可以 ...

  10. 715. Range Module

    A Range Module is a module that tracks ranges of numbers. Your task is to design and implement the f ...