在编写简单的远程测试时,我遇到了一个涉及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();
}
}
}
此代码在运行时发生爆炸,出现以下错误,对我来说没有任何意义:
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) {
//.....
}
}
}
一切正常,序列化顺畅。我甚至试图让测试序列化(颤抖),但是由于测试以更有趣的错误消失了,所以没有产生任何结果 - {{1}应该实现Serializable:)
问题是 - 为什么会这样?研究DBI有点让我相信通过向列表中添加一个元素,这种方式实际上使两个对象 - 预期的HttpInvokerServiceExporter
和一个新的子类 {{ 1}}包含添加元素的对象;这会以某种方式混淆Spring的Remoting并因NotSerializableException而死于可怕的死亡。
但是,我不确定,如果这就是幕后发生的事情,那么任何帮助解释这一点都会受到赞赏。
环境使用以下内容:
答案 0 :(得分:5)
这种情况正在发生,因为双括号初始化语法创建了ArrayList
的匿名子类,并且像所有匿名类一样,它包含对其父对象的隐式引用(在本例中为您的测试)。
为了可序列化,父对象(即您的测试)也必须是可序列化的。这显然不是你想要的。你只需要避免使用这种语法,这很方便。
列表同样方便的替代方案是:
List<SomeBean> mockList = Arrays.asList(
bean1, bean2, bean3
);
构建地图时,DBI语法才真正引人注目。