Google Guice入门教程1

2023-10-21 22:08
文章标签 入门教程 google guice

本文主要是介绍Google Guice入门教程1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文转自:http://www.blogjava.net/xylz/archive/2009/12/22/306955.html 

 

1. 依赖注入

1.1 类依赖注入

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

HelloWorld.java


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

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


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

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


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  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是单例的么?测试下。


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 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么?可以强制转型么?

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

 

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

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


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 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),可以绑定一个实现类到实现类么?

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 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的语法。

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

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


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 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)当然可以!看下面的例子。


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 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>),允许自己提供构造对象的方式。


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  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能够自动寻找实现类。


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

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

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


<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

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


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

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

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  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注解即可。

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 1      @Singleton
2       public   class  HelloWorldImpl  implements  HelloWorld {
3 
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版本进行学习和讨论。

这篇关于Google Guice入门教程1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/257264

相关文章

消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法

消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法   消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法 [转载]原地址:http://blog.csdn.net/x605940745/article/details/17911115 消除SDK更新时的“

Weex入门教程之4,获取当前全局环境变量和配置信息(屏幕高度、宽度等)

$getConfig() 获取当前全局环境变量和配置信息。 Returns: config (object): 配置对象;bundleUrl (string): bundle 的 url;debug (boolean): 是否是调试模式;env (object): 环境对象; weexVersion (string): Weex sdk 版本;appName (string): 应用名字;

Weex入门教程之3,使用 Vue 开发 Weex 页面

环境安装 在这里简略地介绍下,详细看官方教程 Node.js 环境 Node.js官网 通常,安装了 Node.js 环境,npm 包管理工具也随之安装了。因此,直接使用 npm 来安装 weex-toolkit。 npm 是一个 JavaScript 包管理工具,它可以让开发者轻松共享和重用代码。Weex 很多依赖来自社区,同样,Weex 也将很多工具发布到社区方便开发者使用。

Weex入门教程之2,Android Studio安装Weex插件

插件位置及描述 https://plugins.jetbrains.com/idea/plugin/8460-weex 貌似对windows还不是很支持,先放着吧。 安装 插件功能 先预览下都有什么功能 安装完成Weex插件后,如果在main toolbar找不到这些功能图标,那么就需要手动添加到main toolbar 添加到main toolbar 红框内就是

Weex入门教程之1,了解Weex

【资料合集】Weex Conf回顾集锦:讲义PDF+活动视频! PDF分享:链接:http://pan.baidu.com/s/1hr8RniG 密码:fa3j 官方教程:https://weex-project.io/cn/v-0.10/guide/index.html 用意 主要是介绍Weex,并未涉及开发方面,好让我们开始开发之前充分地了解Weex到底是个什么。 以下描述主要摘取于

com.google.gson.JsonSyntaxException:java.lang.IllegalStateException异常

用Gson解析json数据的时候,遇到一个异常,如下图: 这个异常很简单,就是你的封装json数据的javabean没有写对,你仔细查看一下javabean就可以了 比如:我的解析的代码是             Gson gson = new Gson();             ForgetJson rb = gson.fromJson(agResult.mstrJson, For

Python简单入门教程helloworld

Python 学习资源 推荐书籍: Python核心编程(第二版) (强烈推荐,建议有一定基础的看,或者看完简明Python教程再看) Python 基础教程 第二版 (入门,没有核心编程好,但也不错) 编写高质量代码:改善Python程序的91个建议 (进阶,有一定基础再看) 书籍下载: Python 教程(部分内容来源于网络, 历时一年多总结整理的,给刚刚入门的

【超级干货】2天速成PyTorch深度学习入门教程,缓解研究生焦虑

3、cnn基础 卷积神经网络 输入层 —输入图片矩阵 输入层一般是 RGB 图像或单通道的灰度图像,图片像素值在[0,255],可以用矩阵表示图片 卷积层 —特征提取 人通过特征进行图像识别,根据左图直的笔画判断X,右图曲的笔画判断圆 卷积操作 激活层 —加强特征 池化层 —压缩数据 全连接层 —进行分类 输出层 —输出分类概率 4、基于LeNet

Google Earth Engine——高程数据入门和山体阴影和坡度的使用

目录 山体阴影和坡度 对图像应用计算 应用空间减速器 高程数据 通过从“重置”按钮下拉菜单中选择“清除脚本”来清除脚本。搜索“elevation”并单击 SRTM Digital Elevation Data 30m 结果以显示数据集描述。单击导入,将变量移动到脚本顶部的导入部分。将默认变量名称“image”重命名为“srtm”。使用脚本将图像对象添加到地图: Map

The import com.google cannot be resolved

The import com.google cannot be resolved,报错: 第一感觉就是缺少jar包,因为项目用maven管理,所以在pom.xml中添加: <dependency>  <groupId>com.google.code.gson</groupId>  <artifactId>gson</artifactId>  <version>2.3.1</ver