Guice Custom Scopes和Spring托管bean

时间:2022-09-25 10:59:01

(x-posted to guice mailing list)

(x-posted到guice邮件列表)

I'm trialling Guice on a new library that will live in an existing application. All our apps right now are spring apps and we have some common code that is tied to spring, mainly to do with the thread model we tend to use. It basically gives us (what could be seen as) a logical thread.

我正在试用一个将存在于现有应用程序中的新库。我们现在所有的应用程序都是spring应用程序,我们有一些与spring相关的常用代码,主要与我们倾向于使用的线程模型有关。它基本上给了我们(可以看作是什么)一个逻辑线程。

So we can throw jobs at it and it ensures that jobs with a given key always end up on the same pipe in the order that they were submitted. Typically this is a single thread for the life of the application but if bad things happen then the worker thread (that backs the pipe) is thrown away, the pipe deactivated, a new worker created and the pipe reactivated on that worker. All the wiring here is provided by spring.

因此,我们可以在其中抛出作业,并确保具有给定密钥的作业始终按照提交的顺序在同一管道上结束。通常,这是应用程序生命周期中的单个线程,但如果发生坏事,那么工作线程(支持管道)将被丢弃,管道停用,新工作程序创建并且管道在该工作程序上重新激活。这里的所有接线都是由弹簧提供的。

My new lib needs to use this for the thread model & I plan on using guice for the logic & domain side of things, i.e. constructing the work that goes on the pipeline & and the logic that it represents. This seems quite straightforward to me except for one thing that seems quite gnarly, namely that I want to inject certain things with "pipe" (aka logical thread) scope. I've read the custom scopes (and SimpleScope implementation) wiki page but some things are not clear to me and clarification would be much appreciated...

我的新lib需要将它用于线程模型,并且我计划在事物的逻辑和域方面使用guice,即构建管道上的工作及其代表的逻辑。这对我来说似乎很简单,除了一件似乎相当粗糙的事情,即我想用“管道”(又称逻辑线程)范围注入某些东西。我已经阅读了自定义范围(和SimpleScope实现)维基页面,但有些事情我不清楚,澄清将非常感谢...

  1. pipes survive for the life of the JVM therefore it seems that I need to enter a scope but never exit, any downsides to this?
  2. 管道在JVM的生命周期中存活,因此我似乎需要进入一个范围但永远不会退出,这有什么缺点吗?

  3. what options do I have for triggering scope entry in a spring managed bean? is it just a case of creating the spring context and then using the SpringIntegration to suck in the spring beans into a guice context?
  4. 我有什么选择来触发spring托管bean中的作用域条目?它只是创建spring上下文然后使用SpringIntegration将spring bean吸入guice上下文的情况?

  5. does this sound really flaky and I should just wrap it with a singleton keyed by my pipe id instead?
  6. 这听起来真的很不稳定,我应该用一个用我的管道ID键入的单身包裹它吗?

Cheers Matt

1 个解决方案

#1


I've implemented something which works but involves some slightly ugly setup... still interested in any improvements on this & there may be a bit too much code to post really so just put some snippets in that hopefully illuminates

我已经实现了一些可行的但是涉及一些稍微丑陋的设置...仍然对这方面的任何改进感兴趣并且可能有一些太多的代码要发布真的所以只是把一些片段放在那里希望照亮

it's a a variation on the SimpleScope example which involves;

它是SimpleScope示例的一个变体,涉及到;

  • bringing up the spring ctx
  • 提起春天ctx

  • grabbing a specific bean out of it (that is a registry of pipeline keys)
  • 从中获取特定的bean(这是管道键的注册表)

  • passing that to the Guice module along with the beanfactory
  • 将其与beanfactory一起传递给Guice模块

  • giving that registry to the Scope impl so the scope is entered when the pipe is activated (which happens later when certain spring beans are init'ed)
  • 将该注册表赋予Scope impl,以便在激活管道时输入范围(稍后在初始化某些spring bean时发生)

It seems I have to grab the specific bean rather than access it through a Named after doing a bindAll on the beanfactory as the Scope instance is new'ed yourself in the Module, i.e.

看来我必须抓住特定的bean,而不是在beanfactory上执行bindAll后通过Named访问它,因为Scope实例是你自己在模块中新建的,即

    PipeScope<SecurityId> pipeScope = new PipeScope<SecurityId>();
    pipeScope.setPipeIdRegistry(pipeIdRegistry);
    bindScope(Pipe.class, pipeScope);
    bind(PipeScope.class)
            .annotatedWith(Names.named("pipeScope"))
            .toInstance(pipeScope);
    SpringIntegration.bindAll(binder(), beanFactory);

The fact I have to new it means I need to explicitly provide the registry to the module, can't see a way around this as it's a chicken & egg situation.

我必须新的事实意味着我需要明确地向模块提供注册表,无法看到解决这个问题的方法,因为这是一个鸡蛋和鸡蛋的情况。

The PipeScope basically stores values against the pipe key (actually a List of keys) as opposed to a ThreadLocal so my enter is like

PipeScope基本上将值存储在管道密钥(实际上是密钥列表)而不是ThreadLocal,所以我的输入就像

public void enter(List<K> scopedKeys) {
    checkState(values.get(scopedKeys) == null, "A scoping block is already in progress");
    values.put(scopedKeys, Maps.<Key<?>, Object>newHashMap());
}

all in all seems to function perfectly well... at least in my quickly knocked up test harness anyway

总而言之,似乎运作得非常好......至少在我的快速撞击测试带中无论如何

#1


I've implemented something which works but involves some slightly ugly setup... still interested in any improvements on this & there may be a bit too much code to post really so just put some snippets in that hopefully illuminates

我已经实现了一些可行的但是涉及一些稍微丑陋的设置...仍然对这方面的任何改进感兴趣并且可能有一些太多的代码要发布真的所以只是把一些片段放在那里希望照亮

it's a a variation on the SimpleScope example which involves;

它是SimpleScope示例的一个变体,涉及到;

  • bringing up the spring ctx
  • 提起春天ctx

  • grabbing a specific bean out of it (that is a registry of pipeline keys)
  • 从中获取特定的bean(这是管道键的注册表)

  • passing that to the Guice module along with the beanfactory
  • 将其与beanfactory一起传递给Guice模块

  • giving that registry to the Scope impl so the scope is entered when the pipe is activated (which happens later when certain spring beans are init'ed)
  • 将该注册表赋予Scope impl,以便在激活管道时输入范围(稍后在初始化某些spring bean时发生)

It seems I have to grab the specific bean rather than access it through a Named after doing a bindAll on the beanfactory as the Scope instance is new'ed yourself in the Module, i.e.

看来我必须抓住特定的bean,而不是在beanfactory上执行bindAll后通过Named访问它,因为Scope实例是你自己在模块中新建的,即

    PipeScope<SecurityId> pipeScope = new PipeScope<SecurityId>();
    pipeScope.setPipeIdRegistry(pipeIdRegistry);
    bindScope(Pipe.class, pipeScope);
    bind(PipeScope.class)
            .annotatedWith(Names.named("pipeScope"))
            .toInstance(pipeScope);
    SpringIntegration.bindAll(binder(), beanFactory);

The fact I have to new it means I need to explicitly provide the registry to the module, can't see a way around this as it's a chicken & egg situation.

我必须新的事实意味着我需要明确地向模块提供注册表,无法看到解决这个问题的方法,因为这是一个鸡蛋和鸡蛋的情况。

The PipeScope basically stores values against the pipe key (actually a List of keys) as opposed to a ThreadLocal so my enter is like

PipeScope基本上将值存储在管道密钥(实际上是密钥列表)而不是ThreadLocal,所以我的输入就像

public void enter(List<K> scopedKeys) {
    checkState(values.get(scopedKeys) == null, "A scoping block is already in progress");
    values.put(scopedKeys, Maps.<Key<?>, Object>newHashMap());
}

all in all seems to function perfectly well... at least in my quickly knocked up test harness anyway

总而言之,似乎运作得非常好......至少在我的快速撞击测试带中无论如何