在我目前正在工作的项目中,我们开始使用Google Guice。 对于那些不知道的人, Google Guice是一个依赖项注入框架。 依赖项注入背后的基本思想是提供一个它依赖的类,而不是使依赖类负责实例化它所依赖的对象。

Play具有用于整合Guice的模块:
http://www.playframework.org/modules/guice-1.2/home

除了模块文档之外, @ _ felipera的这篇文章还可以帮助您入门。
http://geeks.aretotally.in/dependency-injection-with-play-framework-and-google-guice

如何使用Guice模块

添加依赖项

require:- play- play -> guice 1.2

下载依赖项

play deps

创建一个将注入控制器的新类
services.MyService

package services;
public interface MyService {public void sayHello();
}

services.MyServiceImpl

package services;
public class MyServiceImpl implements MyService {public MyServiceImpl(){play.Logger.info("constructor!");}@Overridepublic void sayHello() {play.Logger.info("hello");}
}

配置进样器

package config;
public class GuiceConfig extends GuiceSupport {@Overrideprotected Injector configure() {return Guice.createInjector(new AbstractModule() {@Overrideprotected void configure() {bind(MyService.class).to(MyServiceImpl.class).in(Singleton.class);}});}
}

这会将类设置为单例。 每次类具有MyService的依赖项时,注入程序都会注入MyServiceImpl的相同实例。

使用@Inject批注注入依赖项

package controllers;
public class Application extends Controller {@Injectstatic MyService myService;public static void index() {myService.sayHello();render();}
}

测试中
我的下一步是创建测试,这是第一个问题

play test

http:// localhost:9000 / @ tests
编译错误! 问题在于该模块有一个名为“ test”的文件夹。 该文件夹应该进行一些单元测试或功能测试,但是它具有三个示例应用程序。 播放模块中的约定是在“ samples and-test”文件夹中具有此类应用程序。

我在项目的分支上重命名了此文件夹:
https://github.com/axelhzf/play-guice-module
我也做了请求请求,但到目前为止我没有得到任何回应: https://github.com/pk11/play-guice-module/pull/5 重命名文件夹“ test”足以运行此测试:

@InjectSupport
public class InjectTest extends UnitTest {@Injectstatic MyService myService;@Testpublic void injectOk(){assertNotNull(myService);}
}

添加更多依赖
默认情况下,Play自动检测类上的@Inject注释,而不是继承自Controller,Job和Mail。 如果要注入对其他类的依赖项,则必须使用@InjectSupport。 通常,我们的服务并不像MyService那样简单。 服务之间具有依赖关系是很常见的。 Guice解决了这个问题,分析了依存关系并以正确的顺序实例化了对象。 services.MyDependentService

package services;public interface MyDependentService {public void sayHelloWorld();
}

service.MyDependentServiceImpl

package services;@InjectSupport
public class MyDependentServiceImpl implements MyDependentService {@Injectstatic MyService myService;public MyDependentServiceImpl(){play.Logger.info("Init MyDependentServiceImpl");}public void sayHelloWorld(){myService.sayHello();play.Logger.info("world");}
}

注入测试

@InjectSupport
public class InjectTest extends UnitTest {@Inject
static MyDependentService myDependentService;@Test
public void injectOk(){assertNotNull(myDependentService);myDependentService.sayHelloWorld();
}}

在GuiceConfig中绑定

bind(MyDependentService.class).to(MyDependentServiceImpl.class).in(Singleton.class);

这是控制台输出

20:34:39,090 INFO ~ Init MyServiceImpl
20:34:39,095 INFO ~ Init MyDependentServiceImpl
20:34:39,095 INFO ~ Application 'lazySingleton' is now started !
20:34:39,136 INFO ~ hello
20:34:39,136 INFO ~ world

构造器注入
我对模块不满意的一件事是,允许您注入的字段必须是静态的。 我宁愿将依赖项声明为构造函数参数。 这样,很明显,要创建MyDependentServiceImpl实例,您需要一个MyService实例。 而且,在进行单元测试时,将模拟对象作为参数传递比配置注入器更容易。 在模块文档中,我没有找到有关如何执行此操作的参考。 不过,我发现了一篇文章,解释了如何使用提供程序来执行此操作: http://ericlefevre.net/wordpress/2011/05/08/play-framework-and-guice-use-providers-in-guice-modules/ 后来,我在StackOverflow上发现了一个问题,这给了我另一个线索: http://stackoverflow.com/questions/8435686/does-injector-getinstance-always-call-a-constructor 他在Edit中说,他忘记将@Inject注释放入构造函数中。 我试图做同样的事情,终于成功了:

public class MyDependentServiceImpl implements MyDependentService {private final MyService myService;@Injectpublic MyDependentServiceImpl(MyService myService){this.myService = myService;play.Logger.info("Inicializando MyDependentServiceImpl");}...

懒惰的单身人士
拥有完善的google guice配置仍然是最后一个细节。
在应用程序启动时初始化服务。

21:38:11,801 INFO ~ Inicializando MyServiceImpl
21:38:11,805 INFO ~ Inicializando MyDependentServiceImpl
21:38:11,805 INFO ~ Application 'lazySingleton' is now started !

当应用程序处于生产模式时,这是正确的行为。 但是在开发模式下,我更喜欢按需初始化Singleton。 可能有一些服务需要花一些时间才能启动,因此我希望应用程序尽快启动。

使用Google Guice,您可以使用Scopes实现此目的:
http://code.google.com/p/google-guice/wiki/范围
您要做的就是设置Stage参数:

Stage stage = Play.mode.isDev() ? Stage.DEVELOPMENT : Stage.PRODUCTION;
return Guice.createInjector(stage, new AbstractModule() {…..

重新运行测试

22:00:03,353 WARN ~ You're running Play! in DEV mode
22:00:04,615 INFO ~ Connected to jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0
22:00:04,811 INFO ~ Guice injector created: config.GuiceConfig
22:00:04,819 INFO ~ Init MyServiceImpl
22:00:04,824 INFO ~ Init MyDependentServiceImpl
22:00:04,824 INFO ~ Application 'lazySingleton' is now started !

哎呀! 在应用程序启动之前初始化Singleton。 也许那不是stage变量的正确用法。 让我们尝试一下测试:

public class StageTest {@Testpublic void testDevelopment(){Injector injector = createInjector(Stage.DEVELOPMENT);System.out.println("development - before getInstance");MyService instance = injector.getInstance(MyService.class);System.out.println("development - after getInstance");}@Testpublic void testProduction(){Injector injector = createInjector(Stage.PRODUCTION);System.out.println("production - before getInstance");MyService instance = injector.getInstance(MyService.class);System.out.println("production - after getInstance");}public Injector createInjector(Stage stage){Injector injector = Guice.createInjector(stage, new AbstractModule(){@Overrideprotected void configure() {bind(MyService.class).to(MyServiceImpl.class);}});return injector;}
}

结果是:

INFO: development - before getInstance
INFO: Inicializando MyServiceImpl
INFO: development - after getInstanceINFO: Inicializando MyServiceImpl
INFO: production - before getInstance
INFO: production - after getInstance

就像文档中说的那样,在开发模式下,Singleton被延迟初始化。
如果这行得通,当我尝试使用播放模块时,为什么不行?

查看代码:
https://github.com/pk11/play-guice-module/blob/master/src/play/modules/guice/GuicePlugin.java
@OnApplicationStart该模块查找所有带有@InjectSupport注释的类,并注入其依赖项。 要注入依赖项,模块调用getBean()方法。 在这里,我们发现了问题:调用getBean()时,该类被实例化。

我找到了解决此问题的方法:
https://groups.google.com/d/msg/google-guice/405HVgnCzsQ/fBUuueP6NfsJ
这是代码:

  • @LazySingleton
  • 更多范围
  • 懒人

这些类为每个标记为@LazySingleton的类创建一个代理。 当注入对象时,注入器实际上会注入代理。 第一次调用方法时,代理将负责初始化类。

使用这些类,注入器配置如下所示:

public class GuiceConfig extends GuiceSupport {@Overrideprotected Injector configure() {Stage stage = Play.mode.isDev() ? Stage.DEVELOPMENT : Stage.PRODUCTION;return Guice.createInjector(stage, new AbstractModule() {@Overrideprotected void configure() {bindScope(LazySingleton.class, MoreScopes.LAZY_SINGLETON);bindLazySingletonOnDev(MyService.class, MyServiceImpl.class);bindLazySingletonOnDev(MyDependentService.class, MyDependentServiceImpl.class);}protected <T> void bindLazySingletonOnDev(Class<T> expected, Class<? extends T> implClass){if(Play.mode.isDev()){bind(implClass).in(MoreScopes.LAZY_SINGLETON);Provider<T> provider = LazyBinder.newLazyProvider(expected, implClass);bind(expected).toProvider(provider);}else{bind(expected).to(implClass).in(Scopes.SINGLETON);}}});}
}

我将把这些类添加到派生中,以便拥有可以在项目之间重用的完整模块。

结论
在过去的几年中,Dependency Injection已经从一个晦涩难懂的术语发展成为每个程序员最精干的一部分。 在本文中,我们看到了将Guice(来自Google的一个非常方便的库)集成到Play框架应用程序有多么容易。 此外,我们还介绍了如何自定义行为,以获得更好的开发体验。

文章原文发表在http://axelhzf.tumblr.com上 。

参考:我们的JCG合作伙伴提供的 Playframework + Google Guice   Sebastian Scarano在“ 玩转Play框架”中! 博客。

翻译自: https://www.javacodegeeks.com/2012/02/play-framework-google-guice.html

玩! 框架+ Google Guice相关推荐

  1. 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享...

    超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 DI框架 Google-Guice入门介绍 转载于:https://www.cnblogs.com ...

  2. guice 框架_玩! 框架+ Google Guice

    guice 框架 在我目前正在工作的项目中,我们开始使用Google Guice. 对于那些不知道的人, Google Guice是一个依赖项注入框架. 依赖项注入的基本思想是提供一个其依赖的类,而不 ...

  3. Google Guice 一个轻量级的依赖注入框架

    1.美图 2.概述 2.1 背景 在做项目的时候,看见有段代码直接是使用Google Guice 注入了avaitor表达式. 2.1 官网 Github 主页:https://github.com/ ...

  4. 玩转Google开源C++单元测试框架

    玩转Google开源C++单元测试框架Google Test系列(gtest)(总) 前段时间学习和了解了下Google的开源C++单元测试框架Google Test,简称gtest,非常的不错. 我 ...

  5. guice google_与Google Guice的动手实践

    guice google by Sankalp Bhatia 通过Sankalp Bhatia 与Google Guice的动手实践 (A hands-on session with Google G ...

  6. Google Guice使用入门

    2019独角兽企业重金招聘Python工程师标准>>> 本文通过范例简单地介绍Google Guice的使用,通过下面的范例我们可以知道,Google Guice的使用非常简单. G ...

  7. guice 实例_使用Google Guice消除实例之间的歧义

    guice 实例 如果接口有多个实现,则Google guice提供了一种精巧的方法来选择目标实现. 我的示例基于Josh Long ( @starbuxman )的出色文章,内容涉及Spring提供 ...

  8. 使用Google Guice消除实例之间的歧义

    如果接口有多个实现,则Google guice提供了一种精巧的方法来选择目标实现. 我的示例基于Josh Long ( @starbuxman )的出色文章,内容涉及Spring提供的类似机制. 因此 ...

  9. Google Guice使用入门(转)

    本文通过范例简单地介绍Google Guice的使用,通过下面的范例我们可以知道,Google Guice的使用非常简单. Google Guice需要使用JDK1.5以上java环境. 下载Goog ...

最新文章

  1. OpenCV Hough Line变换
  2. [入门]C#语法里面,如何使用 VB的常用函数?(using Microsoft.VisualBasic)
  3. Redis 数据库入门教程
  4. wake on lan
  5. ajax向后台传递list参数
  6. Codeforces 475C Kamal-ol-molk#39;s Painting 模拟
  7. 数据结构图之三(最短路径--迪杰斯特拉算法)
  8. [转]_int64、long long 的区别
  9. 数据库系统概念读书笔记-SQL标准简介
  10. 计算机英语ppt答辩,急求英语答辩PPT范文
  11. RSA加解密的OAEP MGF1 填充解析
  12. C语言枚举类 口袋中有红、黄、蓝、白、黑5种颜色的球若干个
  13. i513500h和r5 5600h选哪个 r55600h和i513500h差多少
  14. 感性VS理性-处世之道
  15. 威世 | 新款 LLC 谐振变压器/电感器,优化 PCB 空间布局
  16. 如何正确学习并提高学习效率?
  17. java将实体数据导出到excel,压缩,删除等一系列~
  18. 智能驾驶 车牌检测和识别(二)《YOLOv5实现车牌检测(含车牌检测数据集和训练代码)》
  19. [VM]为Windows Server 2012 R2安装vmtools遇到的问题
  20. 2023计算机毕业设计SSM最新选题之javaJava青年志愿者信息管理系统15925

热门文章

  1. http长/短轮询和WebSocket 的介绍和比较
  2. shebang_Shebang来Java了吗?
  3. java serial_Java的@Serial批注
  4. aws sqs_JMS和AWS SQS的更多高级内容
  5. 怎样编写测试类测试分支_编写干净的测试–从配置开始
  6. 1.0jpa 2.0_JPA 2.1类型转换器–持久枚举的更好方法
  7. java8根据某个id删选_Java 8可选:如何使用它
  8. java 数字 下划线_为什么要在Java SE 7的数字中使用下划线-在数字文字中使用下划线...
  9. 服务网格:Istio和AWS App Mesh
  10. 高级java开发_适用于高级Java开发人员的十大书籍