在我继承的代码库中,有一个 MDB
正在调用SingletonBeanFactoryLocator().getIntance().useBean()
在其 ejbCreate()
中获取工厂引用,然后从该工厂获取特定的 bean 并将其存储为 MDB
实例变量。 (工厂的类型为“ClassPathXmlApplicationContext
”)。
令人困惑的部分是:获得该bean后,它调用' release()
' 在该工厂引用中相同 ejbCreate()
.
现在,这个MDB
与 poolsize ' x
合并' 我观察到的是,context xml
中定义的 beans正在创建'x
' 次数。所以我的猜测是,每次 ' ejbCreate()
' 执行时,它会重新创建一个上下文及其 bean。
我检查了 Spring 文档中的“release()
”上面写着:
In an EJB usage scenario this would normally be called from `ejbRemove()` and `ejbPassivate()`.
这是我的问题:
1) 它真的创建了一个新的上下文和新的bean everytime ejbCreate()
被称为?
2) 如果是,在上一次调用中创建的上下文/bean 会发生什么情况(例如,如果 bean 本身是单例的,它们会被销毁)吗?
3) 这是正确的使用方式 SingletonBeanFactoryLocator
(可能是为了线程安全问题)在上面的上下文中?
4)如果没有,正确的使用方法是什么?
编辑:我能想到的一种可能性是制作相关的 bean prototype
使每个 MDB 实例都是线程安全的,因此无需释放并重新创建上下文。等待其他评论/建议。
最佳答案
- 是
- 什么也没发生。相同的对象仍将位于相同的 MDB 中。 MDB 并不关心,而且 Spring 此时已不再适用。
- 这实际上取决于使用环境。如果您只是使用 Spring 来组装对象,并且每个 MDB 都应该有自己的实例,那么答案是肯定的。
- 根据用例,
SpringBeanAutowiringInterceptor
可能是也可能不是更好的替代方案。 - 原型(prototype)可能很棘手。您必须充分了解您的 bean 及其后果,才能使其达到您的预期。这就是为什么通常最好使 spring beans 无状态。
更新:
实际上存在竞争条件。如果容器决定并行运行两个 MDB 的 ejbCreate()
,那么它们最终将共享相同的应用程序上下文。
更新 2: 我找不到明确允许通过并行线程创建 EJB 的部分,但也找不到明确禁止它的部分。
鉴于规范中的以下部分,我认为这样做符合规范的精神。
<小时/>2.4.2 消息驱动对象
典型的 EJB 容器提供可扩展的运行时环境来同时执行大量消息驱动的对象。
5.2 目标
消息驱动 Bean 模型的进一步目标是允许通过容器提供的消息驱动 Bean 实例池来并发处理消息流。
5.4 消息驱动 Bean 实例与其容器之间的协议(protocol)
容器有责任确保消息驱动的 Bean 在容器启动时就存在,并且该 Bean 的实例在开始消息传递之前已准备好接收异步消息传递。
5.4.11 消息处理并发
容器允许消息驱动 bean 类的许多实例同时执行,从而允许并发处理消息流。尽管容器应该在不损害消息处理并发性的情况下尝试按顺序传递消息,但不保证消息传递到消息驱动 bean 类的实例的确切顺序。
关于Java:MDB 和 Spring 的 SingletonBeanFactoryLocator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11791734/