人们通常希望多个 Web 应用程序共享对单个应用程序上下文的访问。例如这里描述了如何做到这一点。
这个问题正好相反:在单个 Web 应用程序中拥有多个应用程序上下文。通常这很容易,您只需创建并使用它们。
但是,在某些情况下,Spring 方面的静态变量是不可能的,例如:
- 您有两个应用程序上下文 X 和 Y,它们都创建了一个
MyBean
具有@Transactional
注释的 - X 和 Y 都包含自己的事务管理器
- X 和 Y 都有
<tx:annotation-driven mode="aspectj"/>
声明 - 您正在构建时 AspectJ 编织
在这种情况下,问题在于<tx:annotation-driven mode="aspectj"/>
实际上转换为这样的bean:
<bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect"
factory-method="aspectOf"/>
请注意,这会返回 的方面对象AnnotationTransactionAspect
,它是存储在静态变量中的单例。 AnnotationTransactionAspect
extends TransactionAspectSupport
,其中包含实例字段,例如缓存事务管理器。
效果是即使 X 和 Y 中的 bean 完全分离,它们也会在AnnotationTransactionAspect
方面单例中争夺相同的实例字段。这会导致例如“没有正在进行的事务”异常,因为有人得到了错误的事务管理器。
同样的事情也会发生@Configurable
:用于配置 bean 的 bean 工厂存储在一个静态变量中(请参阅 参考资料AnnotationBeanConfigurerAspect.beanConfigurerSupport
)。这是一个更大的问题,因为您可以使用 来避免 AspectJ @Transactional
,但无法使用 来避免它@Configurable
。
我可以想到三个解决方案:
- 停止使用方面
- 写我自己的方面
- 在创建 X 和 Y 的线程中创建/设置新的上下文类加载器
选项 #1 不好,因为我真的很喜欢@Configurable
.
选项 #2 看起来并不有趣。
选项#3 看起来很简单。
那么选项#3如何工作?这是我变得模糊的地方。我需要将 Spring 类加载到 X 和 Y 中的不同类加载器中。这意味着上下文类加载器无法正常委托给它的父级(Web 应用程序类加载器)等。你将如何设置它?
谢谢。