java如何跨不同的VM保留对象标识
具体来说,让我用SpringHTTPRemoting示例来说明这个问题
假设我们有这样一个简单接口的实现:
public SearchServiceImpl implements SearchService {
public SearchJdo processSearch(SearchJdo search) {
search.name = "a funky name";
return search;
}
}
SearchJdo本身就是一个简单的POJO
现在,当我们通过http远程处理从客户端调用该方法时(Spring调用远程对象的机制非常类似于使用序列化的EJB),我们将得到:
public class HTTPClient {
public static void main(final String[] arguments) {
final ApplicationContext context = new ClassPathXmlApplicationContext(
"spring-http-client-config.xml");
final SearchService searchService =
(SearchService) context.getBean("searchService");
SearchJdo search = new SearchJdo();
search.name = "myName";
// this method actually returns the same object it gets as an argument
SearchJdo search2 = searchService.processSearch(search);
System.out.println(search == search2); // prints "false"
}
}
问题是,由于序列化,搜索对象是不同的,尽管从逻辑角度看,它们是相同的
问题是是否有某种技术允许跨VM支持或模拟对象标识
# 1 楼答案
IMHO试图在虚拟机之间保持对象标识平等是一个失败的主张。 据我所知,语言规范不需要VM来支持这一点,因此,如果您真的希望具有可移植性,那么您将受到限制
我可以问一下你为什么不使用你自己提供的一些独特的身份证吗?Java GUI虽然昂贵,但可以序列化
# 2 楼答案
我做过一次,但我不确定这是否是一种正确的方法:
每个用户都将用户名、会话id、角色和登录日期附加到用户对象。每次我登录虚拟机时,系统都会将一个用户对象加载到内存中;我还将用户对象返回到应用程序
如果我需要在应用服务器中执行一个操作,那么我会将用户对象作为参数发送。如果VM使用相同的会话ID加载了用户,那么它将使用VM中存储的对象来了解分配的角色。否则,应用程序将能够更改用户中的角色,因此不安全
如果应用程序必须更改应用程序服务器,那么它会将用户对象发送到新服务器,而新服务器将无法在其记录中找到用户
这里是秘密:会话ID是通过散列用户名、登录日期和所有服务器共享的秘密密码创建的
一旦新服务器发现会话ID是一致的,那么它将从数据库加载角色作为可靠的信息源
对不起,如果我以前不能写这篇文章,但希望它能帮助别人
# 3 楼答案
您说过it-对象标识不同于逻辑相等
==
进行比较.equals(..)
进行比较所以重写
equals()
方法,一切都会好起来的。记住也要基于相同的字段重写hashCode()
。使用IDE为您生成这两种方法(Teracotta VM clustering允许在VM之间共享对象,但这不适合您的情况。)