【问题标题】:Mule/Spring ClassLoader issue when migrating to transaction-api 1.2迁移到 transaction-api 1.2 时的 Mule/Spring ClassLoader 问题
【发布时间】:2017-05-09 02:31:20
【问题描述】:

我正在尝试迁移到 transaction-api 1.2 而不是 jta 1.1。

虽然我知道我可以调整 mule 提供的库,但我无法理解为什么应用程序无法通过仅将 transaction-api 添加到 application/lib 文件夹来工作。没有 transaction-api 一切都按预期工作,但有了它我得到:

Caused by: java.lang.ClassNotFoundException: javax.transaction.Transactional
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[?:1.8.0_66]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_66]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_66]
at org.springframework.transaction.annotation.JtaTransactionAnnotationParser.parseTransactionAnnotation(JtaTransactionAnnotationParser.java:42) ~[spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource.determineTransactionAttribute(TransactionalRepositoryProxyPostProcessor.java:229) ~[?:?]
at org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource.findTransactionAttribute(TransactionalRepositoryProxyPostProcessor.java:208) ~[?:?]
at org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor$AbstractFallbackTransactionAttributeSource.computeTransactionAttribute(TransactionalRepositoryProxyPostProcessor.java:397) ~[?:?]
at org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor$AbstractFallbackTransactionAttributeSource.getTransactionAttribute(TransactionalRepositoryProxyPostProcessor.java:345) ~[?:?]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270) ~[spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]

这里有一些相关的 Spring 代码片段。

spring-data-commons(应用程序/lib):

            if (jta12Present) {
            this.annotationParsers.add(new JtaTransactionAnnotationParser());
        }

地点:

        private static final boolean jta12Present = ClassUtils.isPresent("javax.transaction.Transactional",
            CustomAnnotationTransactionAttributeSource.class.getClassLoader());

- 似乎在将 transaction-api 添加到应用程序时通过了此检查。

JtaTransactionAnnotationParser 来自 mule 提供的 spring-tx(MULE_HOME\lib\opt)。这是它引发异常的地方:

public class JtaTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
    @Override
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
        AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, javax.transaction.Transactional.class); - ClassNotFoundException

为什么 Spring 可以在一个地方识别 Transactional 而在另一个地方却不能?似乎在不同范围内拥有 spring-data-commons 和 spring-tx 可能是原因,但我不明白为什么,因为 Mule 应该提供复杂的分层 ClassLoader 结构并在整个层次结构中搜索。

【问题讨论】:

    标签: java spring mule classloader


    【解决方案1】:

    好的,我想多了,我想我现在理解得更好了。正如我的问题末尾所建议的,这是一个与 ClassLoader 相关的问题。但是,它不是 Mule 或 Spring 特定的。这是普通的旧 ClassLoader 可见性原则:

    可见性原则允许子类加载器看到所有的类 由父类加载器加载,但父类加载器看不到 由孩子加载的类。

    http://javarevisited.blogspot.com/2012/12/how-classloader-works-in-java.html

    在我的例子中,两个依赖的 spring 库最终被单独的 ClassLoader 加载。这就是为什么我强烈建议在将任何具有compile 范围的库添加到应用程序之前检查您的provided 依赖项。如果无法避免歧义,则可以选择管理 ClassLoader 优先级(parent-first vs parent-last)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多