2

我被这个彻底搞糊涂了。我正在运行一个完整的单元测试包。以下是许多 JUnit 测试使用的相关共享代码:

private static Map<String, JAXBContext> jaxbContexts = 
                             new HashMap<String, JAXBContext>();

private synchronized JAXBContext getJAXBContext(Class clazz) throws JAXBException {
    JAXBContext context = null;
    if (jaxbContexts.containsKey(clazz.getName())) {
        context = jaxbContexts.get(clazz.getName());
    } else {
        context = JAXBContext.newInstance(clazz);
        System.out.println("Created new context for '" + clazz.getName() + "'");
        jaxbContexts.put(clazz.getName(), context);
    }
    return context;
}

JUnit 运行的控制台输出包括以下两个连续条目:

Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface'
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface'

我错过了什么?为什么jaxbContexts.containsKey()在这种情况下对于基于字符串的键不起作用,与 JUnit 执行期间的其他 46 次不同?我们没有并行运行我们的测试,但如果这会产生影响,我们会使用 Aspects。

4

5 回答 5

3

对其进行调试并验证包含此 getJAXBContext() 方法的类是否仅实例化一次(通过在调试模式下检查它在每次调用时是否具有相同的内存 ID)。如果是不同的实例化, synchronized 关键字将锁定不同的锁,它们将使用不同的映射。

于 2011-01-20T14:21:51.633 回答
1

就个人而言,我不会打扰 containsKey。

String name = clazz.getName();
context = jaxbContexts.get(name);
if (context == null) {
    context = JAXBContext.newInstance(clazz);
    System.out.println("Created new context for '" + name + "'");
    jaxbContexts.put(name, context);
}
于 2011-01-20T14:21:06.527 回答
1

包含字符串作为键的 Map 肯定没有什么特别之处。只需将 println 替换为new Exception().printStackTrace(),您就会看到发生了什么。您可能正在创建保存地图的类的两个实例,或者其他什么。

于 2011-01-20T14:24:24.157 回答
0

除了比赛...但是你说你不会并行运行...

无论如何,我会打电话context = jaxbContexts.get(clazz.getName())context针对null.

啊,并使用类本身作为键,因为多个类可能具有相同的名称(想想类加载器)

于 2011-01-20T14:22:28.543 回答
-1

地图可以Map<Class, JAXBContext>代替,Map<String, JAXBContext>以便于使用。

于 2011-01-20T14:52:36.960 回答