Java RMI – UnicastRemoteObject:UnicastRemoteObject.exportObject()和扩展UnicastRemoteObject()有什么区别?

我正在准备考试,我有一个问题,我希望有人能回答我。
它关于RMI和远程对象。 我想知道为什么这两个实现之间存在很大差异。 一个是扩展UnicastRemoteObject而另一个是将对象导出为UnicastRemoteObject。
我真的没有区别 – 顺便说一下,这只是一个快速而肮脏的例子:-)

接口:

public interface EchoI extends Remote { public String echo() throws RemoteException } 

这是服务器代码(版本1):

 public class EchoImpl extends UnicastRemoteObject implements EchoI { public EchoImpl { super(); } public static void main (String[] args) { try { LocateRegistry.createRegistry(Registry.REGISTRY_PORT); StoreHouse storehouseImpl = new StorehouseImpl(); Naming.rebind("//localhost/StoreHouse.SERVICE_NAME", storehouseImpl); System.out.println("Server ready"); } catch (RemoteException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } } public String echo() { return "echo"; } } 

这将是版本2:

 public class EchoImpl implements EchoI { public static void main (String[] args) { EchoI echoService = new EchoImpl(); EchoI stub = (EchoI) UnicastRemoteObject.exportObject(echoService, 0); Registry registry = LocateRegistry.getRegistry(); registry.bind("echoService", stub); ... } } 

我的问题是:这两者有什么区别?

在第一个版本中 ,显式创建了注册表,此外,远程对象是在重新绑定中创建的。
我真的很好奇,为什么在第一个我需要自己创建注册表但不需要显式导出对象,只需使用命名重新绑定它。
是之前已经绑定到注册表的对象,还是我可以使用bind? 如果对象之前没有绑定并重新绑定,会发生什么?

第二个版本中 ,注册表似乎已经创建了?
为什么绑定命名与直接绑定到注册表相同?

如果您希望我提供更多详细信息,请给我发表评论……
这就是我的想法:

  • 第一个类direclty实现接口UnicastRemoteObject,这意味着在运行时创建注册表并将对象自动导出到RMI reg。
  • 由于对象已绑定到注册表,因此必须进行重新绑定而不是正常绑定
  • 后者,明确地做了这一切

java.rmi.server.UnicastRemoteObject用于使用Java远程方法协议(JRMP)导出远程对象并获取与远程对象通信的存根。

对于下面的构造函数和静态exportObject方法,获取正在导出的远程对象的存根…

在那里你应该遵循Javadoc

这里有两个问题。

  1. 您可以扩展UnicastRemoteObject或调用UnicastRemoteObject.exportObject(). 你做的由你自己决定。 第一个是简单而自动的; 第二个意味着你可以扩展另一个类。

  2. 您可以使用外部RMI注册表,也可以在服务器JVM中自行创建。 你做的再取决于你,两种方式都有优势。

    这两个问题没有互动。

  3. 如果你extend UnicastRemoteObject你也可以获得hashCode()equals()方法的’远程语义’的好处,这样所有存根看起来都与导出它们的远程对象相同,但这对于它没有实际用处。客户端,实际上只是支持RMI实现本身。

您可以调用UnicastRemoteObject.exportObject()而不是在需要扩展任何其他类的场景中扩展UnicastRemoteObject 。 我认为整体效果是一样的。

看到这个

首先,使用Naming类和Registry类绑定和重新绑定远程对象与类是否正在扩展UnicastRemoteObject方案无关。 请参阅此处了解差异。

其次,扩展UnicastRemoteObject的类之间的区别在于,如果该类型的对象用作存根,那么您不需要再调用UnicastRemoteObject.exportObject来获取存根以便与注册表绑定。 在您的版本1中, StorehouseImpl必须扩展UnicastRemoteObject ,事实上, EchoImpl不需要为您的版本1扩展UnicastRemoteObject ,因为没有EchoImpl实例被注册为注册表的远程对象。

第三,你提到如果在没有预先执行bind情况下执行rebind会发生什么。 正如这里的javadoc所解释的,如果没有插入任何键名,它的行为方式与第一次执行bind行为方式相同。