网站建设与维护实验心得,网站原型图是什么,河南郑州事件,做网站找投资人在我目前正在工作的项目中#xff0c;我们开始使用Google Guice。 对于那些不知道的人#xff0c; Google Guice是一个依赖项注入框架。 依赖项注入背后的基本思想是提供一个它依赖的类#xff0c;而不是使依赖类负责实例化它所依赖的对象。 Play具有用于整合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// localhost9000 / 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注释而不是继承自ControllerJob和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 ~ Youre running Play! in DEV mode
22:00:04,615 INFO ~ Connected to jdbc:h2:mem:play;MODEMYSQL;LOCK_MODE0
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 lt;Tgt; void bindLazySingletonOnDev(Classlt;Tgt; expected, Classlt;? extends Tgt; implClass){if(Play.mode.isDev()){bind(implClass).in(MoreScopes.LAZY_SINGLETON);Providerlt;Tgt; 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