3

人们通常希望多个 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,它是存储在静态变量中的单例。 AnnotationTransactionAspectextends TransactionAspectSupport,其中包含实例字段,例如缓存事务管理器。

效果是即使 X 和 Y 中的 bean 完全分离,它们也会在AnnotationTransactionAspect方面单例中争夺相同的实例字段。这会导致例如“没有正在进行的事务”异常,因为有人得到了错误的事务管理器。

同样的事情也会发生@Configurable:用于配置 bean 的 bean 工厂存储在一个静态变量中(请参阅 参考资料AnnotationBeanConfigurerAspect.beanConfigurerSupport)。这是一个更大的问题,因为您可以使用 来避免 AspectJ @Transactional,但无法使用 来避免它@Configurable

我可以想到三个解决方案:

  1. 停止使用方面
  2. 写我自己的方面
  3. 在创建 X 和 Y 的线程中创建/设置新的上下文类加载器

选项 #1 不好,因为我真的很喜欢@Configurable.

选项 #2 看起来并不有趣。

选项#3 看起来很简单。

那么选项#3如何工作?这是我变得模糊的地方。我需要将 Spring 类加载到 X 和 Y 中的不同类加载器中。这意味着上下文类加载器无法正常委托给它的父级(Web 应用程序类加载器)等。你将如何设置它?

谢谢。

4

0 回答 0