Spring中的Spring/JUnit序列化在Java中初始化了ArrayList

qua*_*tum 0 java serialization

在编写一个简单的远程测试时,我遇到了一个涉及DBI(双括号初始化)的令人惊讶的情况,我一直无法完全理解,所以我会请求一些帮助.

请考虑以下代码:

public class RemotingTest {

@Autowired
private RemotingTestController remotingTestController;

//DBI
List<SomeBean> mockList = new ArrayList<SomeBean>(){{
        add(MockFactoryBean.getMockBean());
}};

@Test
public void testRemoting() {
    try {
        // controller code is not relevant - it simply passes this list 
        // via Spring's HttpInvokerProxyFactoryBean to a session facade which then 
        // passes the list further down the SOA stack...
        String result = remotingTestController.createBeanRemotely(mockList); 
        log.debug(result);
    } catch (Exception e) {
        fail();
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

}

此代码在运行时发生爆炸,出现以下错误,这对我没有意义:

java.io.NotSerializableException: org.stackoverflow.RemotingIntegrationTest
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
  <<stacktrace snipped>>
  at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:174)
  at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:142)
... 33 more

但是,如果我只是省略DBI并使用vanilla样式模式将元素添加到列表中,如下所示:

    public class RemotingTest {

@Autowired
private RemotingTestController remotingTestController;

List<SomeBean> mockList = new ArrayList<SomeBean>();

@Test
public void testRemoting() {
    mockList.add(MockFactoryBean.getEcopStatusMock());

    try {
    //this block stays the same
        } catch (Exception e) {
        //.....
    }
}
Run Code Online (Sandbox Code Playgroud)

}

一切正常,序列化顺利.我甚至试图使测试 Serializable(颤抖),但是没有产生任何结果,因为测试死于一个更有趣的错误 - HttpInvokerServiceExporter应该实现Serializable :)

问题是 - 为什么会这样?研究DBI有点让我相信通过向列表添加元素,这种方式实际上产生了两个对象 - 期望的ArrayList<T>()和包含添加元素的新子类 ArrayList<T>()对象; 这在某种程度上混淆了Spring的Remoting并且死于NotSerializableException的可怕死亡.

然而,我不确定,如果这是幕后发生的事情,那么任何帮助解释这一点都将不胜感激.

环境使用以下内容:

  • Spring 3.0.4
  • JDK 1.6.0更新23
  • IceFaces 1.8.2

ska*_*man 5

发生这种情况是因为双括号初始化语法创建了一个匿名子类ArrayList,并且像所有匿名类一样,它包含对其父对象的隐式引用(在本例中为您的测试).

为了可序列化,父对象(即您的测试)也必须是可序列化的.这显然不是你想要的.你只需要避免使用这种语法,方便的想法就是这样.

列表同样方便的替代方案是:

List<SomeBean> mockList = Arrays.asList(
    bean1, bean2, bean3
);
Run Code Online (Sandbox Code Playgroud)

在构建Maps时,DBI语法才真正引人注目.

  • 在这种情况下(带有单个元素的DBI)[`Collections.singletonList()`](http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#singletonList(T) )是一个很好的替代品.对于更多元素[`Arrays.asList()`](http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html#asList(T ...))很有用(请注意,这是一种varargs方法). (2认同)