如何使用模块而不是插件插入播放生命周期?

Posted

技术标签:

【中文标题】如何使用模块而不是插件插入播放生命周期?【英文标题】:How to plug into the play lifecycle with a module instead of a Plugin? 【发布时间】:2015-07-25 05:36:58 【问题描述】:

我看到 Plugin 类现在已被弃用(从 2.4.x 版本的 play 开始)......在 api 文档中它说我应该使用模块......所以这是我的问题。 如何编写模块,以及如何将该模块插入主应用的播放生命周期?

【问题讨论】:

【参考方案1】:

您没有指定您使用的是哪种语言,因此我将快速介绍这两种语言。我将两个答案都基于以下存储库:

https://github.com/schaloner/deadbolt-2-java https://github.com/schaloner/deadbolt-2-scala

Java

    以您想要的任何方式编写您的功能 - 没有要扩展的特定类。如果你对 Play 组件有依赖,例如 Configuration,你应该注入它们。

    @Singleton
    public class MyModuleCode 
    
        private final boolean enableWidgets;
    
        @javax.inject.Inject
        public MyModuleCode(final Configuration configuration) 
            this.enableWidgets = configuration.getBoolean("widgets.enabled", false);
        
    
    

请注意,使用依赖注入代替静态引用。另外,请注意我给这个例子一个 @Singleton 注释,但也可以有,例如,每个请求的范围。

更多信息请见the Play DI docs

    公开模块的组件。为此,请扩展 play.api.inject.Module 类并实现 public Seq<Binding<?>> bindings(final Environment environment, final Configuration configuration)

    package com.example.module;
    
    public class MyModule extends Module
    
        @Override
        public Seq<Binding<?>> bindings(final Environment environment,
                                        final Configuration configuration)
        
            return seq(bind(MyModuleCode.class).toSelf().in(Singleton.class));
        
    
    

在这里,你还可以将实现绑定到接口,配置实例提供者等等。

    如果您要公开发布该模块,假设您在此处执行此操作 - 这超出了问题的范围。我们还假设您已经为正在处理的任何项目中的模块添加了依赖项。

    启用application.conf中的模块。

    play 
        modules 
            enabled += com.example.module.MyModule
        
    
    

    通过您的模块公开的组件(在此示例中为 MyModuleCode)现在可用于注入到您的控制器、操作等中。

    如果需要关闭钩子,只需将ApplicationLifecycle注入组件并注册钩子即可;详情请见https://playframework.com/documentation/2.4.x/JavaDependencyInjection#Stopping/cleaning-up。

斯卡拉

    以您想要的任何方式编写您的功能 - 没有要扩展的特定类。如果你对 Play 组件有依赖,例如 CacheApi,你应该注入它们。

    @Singleton
    class DefaultPatternCache @Inject() (cache: CacheApi) extends PatternCache 
        override def apply(value: String): Option[Pattern] = cache.getOrElse[Option[Pattern]](key = s"Deadbolt.pattern.$value")  Some(Pattern.compile(value)) 
    
    

请注意,使用依赖注入代替静态引用。另外,请注意我给这个例子一个 @Singleton 注释,但也可以有,例如,每个请求的范围。

更多信息请见the Play DI docs

    公开模块的组件。为此,请扩展 play.api.inject.Module 类并实现 def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]]

    package com.example.module
    
    import com.example.module.cache.DefaultPatternCache, PatternCache
    import play.api.inject.Binding, Module
    import play.api.Configuration, Environment
    
    class MyModule extends Module 
        override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(bind[PatternCache].to[DefaultPatternCache])
    
    

在这里,您还可以将实现绑定到特征、配置实例提供程序等。

    如果您要公开发布该模块,假设您在此处执行此操作 - 这超出了问题的范围。我们还假设您已经为正在处理的任何项目中的模块添加了依赖项。

    启用application.conf中的模块。

    play 
        modules 
            enabled += com.example.module.MyModule
        
    
    

    通过您的模块公开的组件(在此示例中为 MyModuleCode)现在可用于注入到您的控制器、操作等中。

    如果需要关闭钩子,只需将ApplicationLifecycle注入组件并注册钩子即可;详情请见https://playframework.com/documentation/2.4.x/ScalaDependencyInjection#Stopping/cleaning-up。

总结

模块不再是什么特别的东西——它们只是对可注入组件进行分组的一种方式。

【讨论】:

如果我想注册一个 Jackson json 模块怎么办?我应该在哪里这样做(没有全局设置)?我不需要在我的代码中注入某个类的一些实例,我只需要在任何 http 请求之前运行一些代码。 文档中有明确的介绍:playframework.com/documentation/2.4.x/JavaHttpRequestHandlersplayframework.com/documentation/2.4.x/ScalaHttpRequestHandlers 我的意思是,我需要在任何 http 请求发生之前执行此操作,但只有一次,而不是一个 pero 请求。 将包含代码的类声明为一个急切的单例——它会在应用程序启动时运行一次。详情请见playframework.com/documentation/2.4.x/…。

以上是关于如何使用模块而不是插件插入播放生命周期?的主要内容,如果未能解决你的问题,请参考以下文章

Maven:生命周期与阶段与插件与目标的关系[关闭]

如何让自定义视图观察包含片段的生命周期事件而不是活动?

Maven专题3——生命周期与插件

Bean的生命周期流程-上

Bean的生命周期流程-上

深入理解maven构建生命周期和各种plugin插件