玩! 框架+ Google 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已經從一個晦澀難懂的術語發展成為每個程序員最精干的一部分。 在本文中,我們看到了將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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/373307.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373307.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373307.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java都要caps標點_第 1 章 管理 Java CAPS 用戶

第 1 章 管理 Java CAPS 用戶在此處列出的主題提供了有關如何管理 Sun JavaTM Composite Application Platform Suite (Java CAPS) 中的用戶的信息。如果您有任何問題,請參見 http://goldstar.stc.com/ 中的 Java CAPS Web 站點。管理系統信息庫用戶此類別包含以下用…

基于OpenCV 的美顏相機推送直播流

程序流程: 1.圖像采集 先從opencv(2.4.10版本)采集回來攝像頭的圖像,是一幀一幀的 每一幀圖像是一個矩陣,opencv中的mat 數據結構。 2.人臉的美化 人臉美化,我們用的皮膚檢測,皮膚在顏色空間是特…

Linux驅動開發常用頭文件

頭文件目錄中總共有32個.h頭文件。其中主目錄下有13個&#xff0c;asm子目錄中有4個&#xff0c;linux子目錄中有10個&#xff0c;sys子目錄中有5個。這些頭文件各自的功能如下&#xff1a; 1、主目錄 <a.out.h>&#xff1a;a.out頭文件&#xff0c;定義了a.out執行文件格…

Spring線程池服務

線程池對于執行同步和異步過程非常重要。 本文介紹如何使用Spring開發和監視線程池服務。 創建線程池已通過兩種替代方法進行了說明。 二手技術 &#xff1a; JDK 1.6.0_21 Spring3.0.5 Maven的3.0.2 步驟1&#xff1a;建立已完成的專案 創建一個Maven項目&#xff0c;如下…

我的世界java村民繁殖_我的世界:Java19w08a更新,村民加強守衛,小狐貍背叛

雖然這句話很繞口&#xff0c;其實意思很簡單&#xff0c;那就是之前的隱身藥水沒有什么用&#xff0c;該被打還是被打。因為這個可是害慘了流浪商人&#xff0c;不過這次好了&#xff0c;流浪商人在喝了隱身藥水之后就能安全度過晚上了。NO.3 皮革馬鎧馬鎧是屬于馬的盔甲&…

歐萊雅眉筆banner個人設計

眉筆名稱&#xff1a;眉筆大師三頭塑形眉筆 &#xff0c;之所以沒用吧這個商品名稱放大&#xff0c;是我覺得它是一個名稱&#xff0c;而我把自己想的廣告詞“出彩只需一筆” 放大不僅能凸顯出這只筆的強大&#xff0c;還表示了一種有了我這支眉筆你會更出彩更漂亮&#xff0c…

使用帶有注釋和JQuery的Spring MVC 3的Ajax

與Ajax一起工作對我來說一直很有趣&#xff01; 是不是 &#xff1f; 我將使您輕松將Ajax與Spring MVC 3和JQuery結合使用。 這篇文章將向您說明如何在工業編碼的現實生活中使用Ajax。 和往常一樣&#xff0c;我們將在Spring MVC 3框架中以Ajax的實際示例為例&#xff0c;并將其…

ThinkPHP 3 的輸出

一、ThinkPHP 3 的輸出 &#xff08;重點&#xff09;a、通過 echo 等PHP原生的輸出方式在頁面中輸出b、通過display方法輸出想分配變量可以使用assign方法c、修改左右定界符休要修改配置文件中的配置項TMPL_L_DELIM><{, //修改左定界符TMPL_R_DELIM>}>, //修…

java百度云文件上傳_關于如何在自己項目集成百度云BCE文件上傳STS方案

1、 項目背景由于本人項目需要&#xff0c;需要在視頻點播服務之中需要加載字幕文件(通用格式srt)&#xff0c;經過比較好幾家的公有云服務&#xff0c;最后選擇只有百度云提供字幕服務。字幕&#xff1a;我們通常在觀看外語電影的是&#xff0c;沒有國語版時候只能通過下載字幕…

Java 7 – NIO文件革命

Java 7&#xff08;“項目代幣”&#xff09;已于去年7月問世。 此版本中的新增功能很有用&#xff0c;例如&#xff0c;嘗試使用資源–從try塊自動處理可關閉的資源&#xff0c;switch語句中的字符串&#xff0c;用于異常的multicatch以及用于使用泛型的<>運算符。 每個…

hdu 3507 Print Article(斜率優化DP)

題目鏈接&#xff1a;hdu 3507 Print Article 題意&#xff1a; 每個字有一個值&#xff0c;現在讓你分成k段打印&#xff0c;每段打印需要消耗的值用那個公式計算&#xff0c;現在讓你求最小值 題解&#xff1a; 設dp[i]表示前i個字符需要消耗的最小值&#xff0c;那么有dp[i]…

第三章 consul服務注冊與服務查詢

1、定義一個服務 https://www.consul.io/docs/agent/services.html 該方法是服務注冊中提供服務的最常用的方法。 關于服務的定義&#xff1a;服務的屬性我們會在后邊每出現一個總結一個&#xff0c;最后再做總結。 2、服務注冊 2.1、創建服務文件所存放的文件夾 說明&#xff…

coreos 安裝mysql_CoreOS 在 PC 上快速安裝方法指南

意義能夠以最快的速度安裝部署Linux操作系統。安裝快速簡單&#xff0c;幾乎不花時間就可以開始運行Docker。運行速度非常快。使用內存硬盤。我的情況win8 筆記本偶爾玩游戲&#xff0c;但是裝Linux雙系統可能需要我一天的時間來完成。我的所有業務都只需要在Docker中跑就可以了…

使用ycsb測試cassandra

參考 https://github.com/cloudius-systems/osv/wiki/Benchmarking-Cassandra-and-other-NoSQL-databases-with-YCSB https://github.com/brianfrankcooper/YCSB/tree/master/cassandra 創建 表頭 https://gist.github.com/pbailis/3978273  設置field參數 長度和個數 啟動和…

Session 的配置和特性

session的配置 對于session的配置是php.ini中配置 session數據都是保存在文本文件中 設置session文件的保存位置 說明&#xff1a; 默認是保存在windows/temp目錄 設置session保存作為客戶端標識的數據使用cookie 設置session保存客戶端標識的數據&#xff0c;只使用cookie 說明…

OAuth與Spring Security

摘自Wikipedia&#xff1a; OAuth &#xff08; 開放式身份驗證 &#xff09;是一種開放式身份驗證標準。 它允許用戶與其他站點共享存儲在一個站點上的私有資源&#xff08;例如照片&#xff0c;視頻&#xff0c;聯系人列表&#xff09;&#xff0c;而不必發出其憑據&#xff…

flex java 開發環境搭建_Flex+JAVA+BlazeDS開發環境配置(Java工程和Flex工程獨立)

FlexJAVABlazeDS開發環境配置(Java工程和Flex工程獨立)2019年12月07日閱讀數&#xff1a;7這篇文章主要向大家介紹FlexJAVABlazeDS開發環境配置(Java工程和Flex工程獨立),主要內容包括基礎應用、實用技巧、原理機制等方面&#xff0c;希望對大家有所幫助。[url]http://blog.csd…

1251 括號(遞歸小練)

1251 括號 時間限制: 1 s空間限制: 128000 KB題目等級 : 黃金 Gold題目描述 Description計算乘法時&#xff0c;我們可以添加括號&#xff0c;來改變相乘的順序&#xff0c;比如計算              X1, X2, X3, X4, …, XN的積&#xff0c;可以 (X1(X2(X3(X4(...(XN-1…

zabbix_agentd.conf配置文件詳解

Aliaskey的別名&#xff0c;例如 Aliasttlsa.userid:vfs.file.regexp[/etc/passwd,^ttlsa:.:([0-9]),,,,\1]&#xff0c; 或者ttlsa的用戶ID。你可以使用key&#xff1a;vfs.file.regexp[/etc/passwd,^ttlsa:.: ([0-9]),,,,\1]&#xff0c;也可以使用ttlsa.userid。備注: 別名不…

在運行時修補Java

本文將重點介紹如何解決與第三方庫相關的問題 不能被規避 難以排除/繞過/替換 只需不提供錯誤修正 在這種情況下&#xff0c;解決問題仍然是一項艱巨的任務。 作為這種情況的誘因&#xff0c;請考慮對“哈希索引”數據結構的攻擊&#xff0c;例如java.util.Hashtable和java…