guice 框架_玩! 框架+ Google Guice

guice 框架

在我目前正在工作的项目中,我们开始使用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已经从一个晦涩难懂的术语演变为每个程序员最精干的一部分。 在本文中,我们看到了将来自Google的一个非常方便的库Guice集成到一个Play框架应用程序有多么容易。 此外,我们还介绍了如何自定义行为,以获得更好的开发体验。

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

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


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

guice 框架

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js中,实现对键盘按键的监听:

<script>function keyUp(e) { var currKey0,ee||event; currKeye.keyCode||e.which||e.charCode; var keyName String.fromCharCode(currKey); alert("按键码: " currKey " 字符: " keyName); } document.onkeyup keyUp;</scrip…

java程序运行结果题_2016年关于Java编程与程序运行结果笔试题

2016年关于Java编程与程序运行结果笔试题1.Java编程,打印昨天的当前时刻public class YesterdayCurrent{public void main(String[] args){Calendar cal Calendar.getInstance();cal.add(Calendar.DATE, -1);System.out.println(cal.getTime());}}2.文件读写,实现一个计数器pu…

Hystrix简介– Hello World

在先前的博客文章中&#xff0c;我谈到了需要像Netflix Hystrix这样的库的动机。 在这里&#xff0c;我将跳入一些非常基本的方法来开始使用Hystrix&#xff0c;并在更复杂的用例中进行后续介绍。 你好&#xff0c;世界 以下是“ Hystrix命令”的一个简单的Hello World示例&am…

Unity 继承MonoBehaviour下方法通过鼠标触控与物体交互

要通过鼠标的进入、离开、悬停、拖拽等动作实现与物体的交互时&#xff0c;我们可以使用继承MonoBehaviour的脚本下的与鼠标相关的方法。具体有以下方法&#xff1a; //当鼠标按下时被调用private void OnMouseDown(){Debug.Log("鼠标按下了");}//当鼠标按下并拖动时…

Collection中list集合的应用常见的方法

集合 &#xff1a; 用存放对象的容器(集合) Collection &#xff1a; 跟接口 &#xff1a; 单列集合 ---> List :有序的 &#xff0c;元素是可以重复的。 ---> Set : 无序的 &#xff0c;元素是不可以重复的。 Collectionz红常用的方…

js base64编码 java 解码_JavaScript字符串的Base64编码与解码

有时文本里包含一些不可打印的符号&#xff0c;而你需要把它们传输到服务器&#xff0c;这时我们会需要用到Base64编码。或者你需要把一个图片内容以文本格式嵌入到网页中&#xff0c;这时你也会用到 Base64 编码。所谓 Base64 是一种基于64个可打印字符来表示二进制数据的方法…

linux cmake 安装mysql5.5.11_以及更高版本_linux cmake 安装mysql5.5.11,以及更高版本

1、下载mysql5.5.12和cmakewgethttp://mirrors.sohu.com/mysql/MySQL-5.5/mysql-5.5.12-linux2.6-i686.tar.gzwget http://www.cmake.org/files/v2.8/cmake-2.8.4.tar.gz2、安装cmakemkdir /usr/local/cmake切换到存放cmake-2.8.4.tar.gz到目录tar zxvfcmake-2.8.4.tar.gzcd cm…

iOS中如何监测来电

http://blog.csdn.net/liujinlongxa/article/details/44207587转载于:https://www.cnblogs.com/it-k-50/p/6122844.html

maven 构建依赖树_Maven构建依赖项

maven 构建依赖树熟悉发行版和快照依赖关系的Maven和Gradle用户可能不了解TeamCity快照依赖关系&#xff0c;或者假定他们与Maven相关&#xff08;这是不正确的&#xff09;。 熟悉工件和快照相关性的TeamCity用户可能不知道&#xff0c;除了TeamCity提供的功能之外&#xff0c…

ssh图片上传 java_ssh上传并显示图片

struts部分&#xff1a;attribute"upfileForm"input"/upload/uploadfile.jsp"name"upfileForm"path"/upfile"scope"request"validate"true"type"com.yourcompany.struts.action.UpfileAction">publi…

安卓手机移动端页面为body设置overflow:hidden;不起作用

动态的改变body的样式&#xff0c;测试了可行 var scrollTop $("body").scrollTop();//body设置为fixed之后会飘到顶部&#xff0c;所以要动态计算当前用户所在高度 $("body").css({overflow:hidden,position: fixed,top: scrollTop*-1 }); $loadMask.css…

责任链设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

HDU 5944 Fxx and string(暴力/枚举)

传送门 Fxx and string Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 1007 Accepted Submission(s): 422 Description Problem DescriptionYoung theoretical computer scientist Fxx get a string which co…

经典的java程序_Java经典程序

}}}-----------------结果&#xff1a;ABDCBDCB-----------------2.写出程序运行结果import java.lang.StringBuffer;public class Test2{public static void stringReplace(String str){str str.replace(j,i);}public static void bufferReplace(StringBuffer sbf){sbf sbf.…

继续OI

NOIP2016于2016.11.20日12:00正式结束。 我作为oi的生涯 或许会结束&#xff1f; 或者继续&#xff1f; 然而前途依然迷茫&#xff0c;我是否应该继&#xff1f;或是放弃&#xff1f; 距离省选还有3~4个月&#xff0c;我该何去何从&#xff1f; 虽然已经经历过联赛&#xff0c;…

java存储过程示例_安全密码存储–请勿做的事和Java示例

java存储过程示例安全存储密码的重要性 作为软件开发人员&#xff0c;我们最重要的职责之一就是保护用户的个人信息。 如果没有我们应用程序的技术知识&#xff0c;用户别无选择&#xff0c;只能相信我们正在履行这一责任。 令人遗憾的是&#xff0c;在密码方面&#xff0c;软件…

背包问题 贪心算法 java_JS基于贪心算法解决背包问题

前面我们分享了关于js使用贪心算法解决找零问题&#xff0c;本文我们接着为大家介绍JS基于贪心算法解决背包问题。贪心算法&#xff1a;在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;他所做出的仅是在某…

Nginx配置proxy_pass

nginx配置proxy_pass&#xff0c;需要注意转发的路径配置 1、location /test/ { proxy_pass http://t6:8300; } 2、location /test/ { proxy_pass http://t6:8300/; } 上面两种配置&#xff0c;区别只在于proxy_pass转发的路径后是否带 “/” 针对情况1 如果访问url ht…

java代码耗尽内存_有关Java内存溢出及内存消耗的小知识

内存溢出原理&#xff1a;我们知道&#xff0c;Java程序本身是不能直接在计算机上运行的&#xff0c;它需要依赖于硬件基础之上的操作系统和JVM(Java虚拟机)。Java程序启动时JVM都会分配一个初始内存和最大内存给这个应用程序。这个初始内存和最大内存在一定程度上会影响应用程…

简单一致的Log4j2 Logger命名

在带有Java 7方法句柄的可移植记录器名称一文中 &#xff0c;我写了关于使用Java 7的方法句柄来命名类的记录器的文章。 我在那篇文章中说过&#xff0c;这种方法的优点包括记录器命名的一致性&#xff0c;避免了意外的代码复制和粘贴&#xff0c;这可能会导致将不同的类名用作…