3

我遇到了一个可能与 Spring / 类加载器关系有关的问题。

我现在为这个问题的冗长道歉。

我有许多最初编写并打算在专用 JVM 中运行的遗留 Java 应用程序。我们在检查资源使用情况后决定,可以通过在单个 JVM 中运行多个应用程序来提高效率。在这种情况下,我编写了一个专门为我们的环境设计的容器管理器,它能够在容器(或沙箱)中运行每个应用程序。这种隔离容器的能力的基础当然是自定义类加载器。

一切正常,直到我们遇到一个使用 Spring 框架的应用程序。我有一个带有片段的 Spring 配置文件,如下所示。

<bean id="MDDStructurPackager" class="abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000">
    <property name="logger">
        <ref local="Logger"/>
    </property>
    <property name="realm">
        <value>unpack</value>
    </property>
</bean>

<bean id="Jakarta" class="abc.def.mdd.channel.corba.M2000AlarmChannel">
    <constructor-arg>
        <ref bean="MDDStructurPackager"/>
    </constructor-arg>
    <property name="interactionLayer">
        <ref local="MDDInteractionLayer"/>
    </property>
    <property name="logger">
        <ref local="Logger"/>
    </property>
    <property name="tempFile" value="/opt/app/abcdef/rt_dev/var/cache/dat/Huawei_M2000_Jakarta.dat"/>
    <property name="host" value="M2000Jakarta.ior"/>
    <property name="irpReference" value="clarity"/>
    <property name="name" value="M2000Jakarta"/>
    <property name="realm" value="Jakarta"/>
	<property name="natAddress" value="99.999.99.9" />
</bean>


以下是 Spring 实例化 bean 时日志文件的片段。

调试 [South Agent 1] (DefaultSingletonBeanRegistry.java:162) - 创建单例 bean 'MDDStructurPackager' 的共享实例

调试 [South Agent 1] (AbstractAutowireCapableBeanFactory.java:378) - 创建 bean 'MDDStructurPackager' 的实例

调试 [South Agent 1] (AbstractAutowireCapableBeanFactory.java:453) - 急切地缓存 bean 'MDDStructurPackager' 以允许解析潜在的循环引用

调试 [South Agent 1] (AbstractBeanFactory.java:213) - 返回单例 bean 'Logger' 的缓存实例

DEBUG [South Agent 1] (CachedIntrospectionResults.java:242) - 获取类 [abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000] 的 BeanInfo

DEBUG [South Agent 1] (CachedIntrospectionResults.java:258) - 缓存类 [abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000] 的 PropertyDescriptors

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.Class] 的 bean 属性“类”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“colectionDate”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型为 [abc.def.mdd.msg.MDDComponent] 的 bean 属性“组件”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“fileType”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型为 [java.util.ArrayList] 的 bean 属性“listCommonWords”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到 [java.util.ArrayList] 类型的 bean 属性“listHeader”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到 [abc.def.mdd.logger.Logger] 类型的 bean 属性“记录器”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.util.Map] 的 bean 属性“mapDelimiter”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到 [java.util.Map] 类型的 bean 属性“mapElement”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“namePackager”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“nameSpaceXMLSchema”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“nodeName”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“packageXMLSchema”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [abc.def.mdd.channel.ProcessingLayerListener] 的 bean 属性“processingLayerListener”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“领域”

调试 [South Agent 1] (CachedIntrospectionResults.java:267) - 找到类型 [java.lang.String] 的 bean 属性“statesObject”

DEBUG [South Agent 1] (AbstractAutowireCapableBeanFactory.java:406) - 完成创建 bean 'MDDStructurPackager' 的实例

调试 [South Agent 1] (DefaultSingletonBeanRegistry.java:162) - 创建单例 bean 'ListAlarmChannel' 的共享实例

调试 [South Agent 1] (AbstractAutowireCapableBeanFactory.java:378) - 创建 bean 'ListAlarmChannel' 的实例

调试 [South Agent 1] (AbstractAutowireCapableBeanFactory.java:453) - 急切地缓存 bean 'ListAlarmChannel' 以允许解析潜在的循环引用

调试 [South Agent 1] (DefaultSingletonBeanRegistry.java:162) - 创建单例 bean 'Jakarta' 的共享实例

调试 [South Agent 1] (AbstractAutowireCapableBeanFactory.java:378) - 创建 bean 'Jakarta' 的实例

调试 [South Agent 1] (AbstractBeanFactory.java:213) - 返回单例 bean 'MDDStructurPackager' 的缓存实例

信息:CORBA_HUAWEI_M2KJKT_ALARM (23447542):在类路径中添加了“/opt/app/abcdef/rt_dev/lib/logkit-1.2.jar”。

信息:CORBA_HUAWEI_M2KJKT_ALARM (23447542):在类路径中添加了“/opt/app/abcdef/rt_dev/lib/avalon-framework-4.1.5.jar”。

信息:CORBA_HUAWEI_M2KJKT_ALARM (23447542):在类路径中添加了“/opt/app/abcdef/rt_dev/lib/concurrent-1.3.2.jar”。

信息:CORBA_HUAWEI_M2KJKT_ALARM (23447542):在类路径中添加了“/opt/app/abcdef/rt_dev/lib/antlr-2.7.2.jar”。

调试 [South Agent 1] (ConstructorResolver.java:195) -
忽略构造函数 [public abc.def.mdd.channel.corba.M2000AlarmChannel(
java.lang.String, int, java.lang.String, java.lang.String, com.citycorp.mdd.msg.MDDComponent )抛出
bean 'Jakarta' 的 java.lang.Exception ]:org.springframework.beans.factory.UnsatisfiedDependencyException:
创建文件 [/opt/app/ 中定义的名称为 'Jakarta' 的 bean 时出错abcdef/rt_dev/etc/HUAWEI_M2KJKT_ALARM.xml]:
通过构造函数参数表达的不满足的依赖关系,索引为0,类型为[java.lang.String]:
无法将类型 [abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000] 的构造函数参数值转换为所需类型 [java.lang.String]:
无法转换类型 [abc.def.mdd.msg.alarm] 的值.huawei.MDDPackagerAlarmM2000] 到所需类型 [java.lang.String];
嵌套异常是 java.lang.IllegalArgumentException:无法将类型 [abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000] 的值转换为所需类型 [java.lang.String]:
找不到匹配的编辑器或转换策略


以下是 abc.def.mdd.channel.corba.M2000AlarmChannel 类的构造函数的签名:

公共 M2000AlarmChannel(MDDComponent 组件)

public M2000AlarmChannel(String host, int port, String username, String password, MDDComponent componenet)

abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000类实现了MDDComponent(bean MDDStructurPackager)。



如您所见,Spring 正在实例化一些 bean,即。MDDStructurPackager 没有问题。

问题是实例化“Jakarta”bean。

线条的含义:

在文件 [/opt/app/abcdef/rt_dev/etc/HUAWEI_M2KJKT_ALARM.xml] 中定义名称为“Jakarta”的 bean 创建错误:

通过类型为 [java.lang.String] 的索引 0 的构造函数参数表示的不满足依赖关系:

无法将类型 [abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000] 的构造函数参数值转换为所需类型 [java.lang.String]:

不清楚。在尝试确定适当的构造函数时,我不确定类型混淆的原因。问题可能与接口 MDDComponent 的加载有关。如果它被加载两次,在类加载器层次结构中不相关的不同类加载器,您可以想象与确定正确构造函数相关的问题。

任何感激地接受的想法,我都在抓住稻草。

谢谢布莱恩

4

3 回答 3

3

从错误消息中,听起来 Spring 正在尝试使用此构造函数实例化对象:

public M2000AlarmChannel(String host, int port, String username, String password, MDDComponent componenet)

看起来 Spring 对使用哪个构造函数感到困惑,可能是因为两个构造函数都有一个MDDComponent参数(在某种程度上,两个构造函数都将 this 作为最后一个参数,我很好奇这是否与 Spring 在确定时使用的逻辑有关使用哪个构造函数。无论如何......)。

根据Spring 手册,您可以向<constructor-arg>元素添加一些参数,以帮助容器解析要使用的构造函数:

您可以添加“类型”:

<bean id="exampleBean" class="examples.ExampleBean">
  <constructor-arg type="int" value="7500000"/>
  <constructor-arg type="java.lang.String" value="42"/>
</bean>

或者你可以添加一个索引:

<bean id="exampleBean" class="examples.ExampleBean">
  <constructor-arg index="0" value="7500000"/>
  <constructor-arg index="1" value="42"/>
</bean>

(如果你真的想,你可以同时指定两者)

添加其中一个或两个应该有助于 Spring 解决要使用的构造函数。

作为推论,如果这没有帮助,您是否可以简单地更改 XML 定义以传递另一个构造函数所需的参数,即 Spring 试图使用的构造函数?

顺便说一句,在 WMD 中使用引号标签可能会使您的问题更具可读性。

于 2009-02-17T00:01:11.280 回答
0

事实上,我认为是。您传递给 Jakarta 对象的第一个构造函数参数的类型为 abc.def.mdd.msg.alarm.huawei.MDDPackagerAlarmM2000,但 ctor 需要一个字符串。使类型正确匹配。

它读作直截了当的消息。我错过了什么?

我将从包结构中假设这些是您的类。真的?

于 2009-02-16T23:23:54.910 回答
0

你能控制AlarmChannel班级吗?如果是这样,您是否可以滚动一个在构造函数中具有打印语句的新版本(您也可以在初始化程序中使用try-catchstatic初始化类的位置获取堆栈跟踪)?

这样,您可能会了解是否涉及重复的类

同样在 Spring 配置文件中,您可以ClassLoader使用 a 打印出MethodInvokingFactoryBean- 这也可能对此事有所帮助?

于 2009-02-16T23:37:25.173 回答