玩! 框架+ 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模塊
添加依賴項(xiàng)
require:- play- play -> guice 1.2下載依賴項(xiàng)
play deps 創(chuàng)建一個(gè)將注入控制器的新類
services.MyService
services.MyServiceImpl
package services; public class MyServiceImpl implements MyService {public MyServiceImpl(){play.Logger.info("constructor!");}@Overridepublic void sayHello() {play.Logger.info("hello");} }配置進(jìn)樣器
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);}});} }這會(huì)將類設(shè)置為單例。 每次類具有MyService的依賴項(xiàng)時(shí),注入程序都會(huì)注入MyServiceImpl的相同實(shí)例。
使用@Inject批注注入依賴項(xiàng)
package controllers; public class Application extends Controller {@Injectstatic MyService myService;public static void index() {myService.sayHello();render();} } 測(cè)試中
我的下一步是創(chuàng)建測(cè)試,這是第一個(gè)問題
http:// localhost:9000 / @ tests
編譯錯(cuò)誤! 問題在于該模塊有一個(gè)名為“ test”的文件夾。 該文件夾應(yīng)該進(jìn)行一些單元測(cè)試或功能測(cè)試,但是它具有三個(gè)示例應(yīng)用程序。 播放模塊中的約定是在“ samples and-test”文件夾中具有此類應(yīng)用程序。
我在項(xiàng)目的分支上重命名了此文件夾:
https://github.com/axelhzf/play-guice-module
我也做了請(qǐng)求請(qǐng)求,但到目前為止我沒有得到任何回應(yīng): https://github.com/pk11/play-guice-module/pull/5 重命名文件夾“ test”足以運(yùn)行此測(cè)試:
添加更多依賴
默認(rèn)情況下,Play自動(dòng)檢測(cè)類上的@Inject注釋,而不是繼承自Controller,Job和Mail。 如果要注入對(duì)其他類的依賴項(xiàng),則必須使用@InjectSupport。 通常,我們的服務(wù)并不像MyService那樣簡單。 服務(wù)之間具有依賴關(guān)系是很常見的。 Guice解決了這個(gè)問題,分析了依存關(guān)系并以正確的順序?qū)嵗藢?duì)象。 services.MyDependentService
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");} }注入測(cè)試
@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);這是控制臺(tái)輸出
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 構(gòu)造器注入
我對(duì)模塊不滿意的一件事是,允許您注入的字段必須是靜態(tài)的。 我寧愿將依賴項(xiàng)聲明為構(gòu)造函數(shù)參數(shù)。 這樣,很明顯,要?jiǎng)?chuàng)建MyDependentServiceImpl實(shí)例,您需要一個(gè)MyService實(shí)例。 而且,在進(jìn)行單元測(cè)試時(shí),將模擬對(duì)象作為參數(shù)傳遞比配置注入器更容易。 在模塊文檔中,我沒有找到有關(guān)如何執(zhí)行此操作的參考。 不過,我發(fā)現(xiàn)了一篇文章,解釋了如何使用提供程序來執(zhí)行此操作: http://ericlefevre.net/wordpress/2011/05/08/play-framework-and-guice-use-providers-in-guice-modules/ 后來,我在StackOverflow上發(fā)現(xiàn)了一個(gè)問題,這給了我另一個(gè)線索: http://stackoverflow.com/questions/8435686/does-injector-getinstance-always-call-a-constructor 他在Edit中說,他忘記將@Inject注釋放入構(gòu)造函數(shù)中。 我試圖做同樣的事情,終于成功了:
懶惰的單身人士
擁有完善的google guice配置仍然是最后一個(gè)細(xì)節(jié)。
在應(yīng)用程序啟動(dòng)時(shí)初始化服務(wù)。
當(dāng)應(yīng)用程序處于生產(chǎn)模式時(shí),這是正確的行為。 但是在開發(fā)模式下,我更喜歡按需初始化Singleton。 可能有一些服務(wù)需要花一些時(shí)間才能啟動(dòng),因此我希望應(yīng)用程序盡快啟動(dòng)。
使用Google Guice,您可以使用Scopes實(shí)現(xiàn)此目的:
http://code.google.com/p/google-guice/wiki/范圍
您要做的就是設(shè)置Stage參數(shù):
重新運(yùn)行測(cè)試
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 !哎呀! 在應(yīng)用程序啟動(dòng)之前初始化Singleton。 也許那不是stage變量的正確用法。 讓我們嘗試一下測(cè)試:
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;} }結(jié)果是:
INFO: development - before getInstance INFO: Inicializando MyServiceImpl INFO: development - after getInstanceINFO: Inicializando MyServiceImpl INFO: production - before getInstance INFO: production - after getInstance 就像文檔中說的那樣,在開發(fā)模式下,Singleton被延遲初始化。
如果這行得通,當(dāng)我嘗試使用播放模塊時(shí),為什么不行?
查看代碼:
https://github.com/pk11/play-guice-module/blob/master/src/play/modules/guice/GuicePlugin.java
@OnApplicationStart該模塊查找所有帶有@InjectSupport注釋的類,并注入其依賴項(xiàng)。 要注入依賴項(xiàng),模塊調(diào)用getBean()方法。 在這里,我們發(fā)現(xiàn)了問題:調(diào)用getBean()時(shí),該類被實(shí)例化。
我找到了解決此問題的方法:
https://groups.google.com/d/msg/google-guice/405HVgnCzsQ/fBUuueP6NfsJ
這是代碼:
- @LazySingleton
- 更多范圍
- 懶人
這些類為每個(gè)標(biāo)記為@LazySingleton的類創(chuàng)建一個(gè)代理。 當(dāng)注入對(duì)象時(shí),注入器實(shí)際上會(huì)注入代理。 第一次調(diào)用方法時(shí),代理將負(fù)責(zé)初始化類。
使用這些類,注入器配置如下所示:
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);}}});} }我將把這些類添加到派生中,以便擁有可以在項(xiàng)目之間重用的完整模塊。
結(jié)論
在過去的幾年中,Dependency Injection已經(jīng)從一個(gè)晦澀難懂的術(shù)語發(fā)展成為每個(gè)程序員最精干的一部分。 在本文中,我們看到了將Guice(來自Google的一個(gè)非常方便的庫)集成到Play框架應(yīng)用程序有多么容易。 此外,我們還介紹了如何自定義行為,以獲得更好的開發(fā)體驗(yàn)。
文章原文發(fā)表在http://axelhzf.tumblr.com上 。
參考:我們的JCG合作伙伴提供的 Playframework + Google Guice ? Sebastian Scarano在“ 玩轉(zhuǎn)Play框架”中! 博客。
翻譯自: https://www.javacodegeeks.com/2012/02/play-framework-google-guice.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的玩! 框架+ Google Guice的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (交通事故备案后时效)
- 下一篇: 扩展您的JPA POJO