2009-11-16 30 views
2

我在Spring上公开了一些使用RMI的服务。每个服务都有一个对其他服务bean的依赖,这个服务bean执行真正的处理任务。例如:RMI公开服务中的引用是否应该是暂时的?

<bean id="accountService" class="example.AccountServiceImpl"> 
    <!-- any additional properties, maybe a DAO? --> 
</bean> 

<bean id="rmiAccount" class="example.AccountRmiServiceImpl"/> 

<bean class="org.springframework.remoting.rmi.RmiServiceExporter"> 
    <!-- does not necessarily have to be the same name as the bean to be exported --> 
    <property name="serviceName" value="AccountService"/> 
    <property name="service" ref="accountService"/> 
    <property name="serviceInterface" value="example.AccountService"/> 
    <!-- defaults to 1099 --> 
    <property name="registryPort" value="1199"/> 
</bean> 

我AccountRmiServiceImpl看起来是这样的:

public class AccountRmiServiceImpl implements AccountRmiService { 
    private static final long serialVersionUID = -8839362521253363446L; 

    private AccountService accountService; 

    @Autowired 
    public void setAccountService(AccountService accountService) { 
     this.accountService = accountService; 
    } 
} 

我的问题是:能不AccountServiceImpl实现Serializable标记接口产生的呢?如果是这样的话,那么它在AccountRmiServiceImpl中的引用应该是短暂的。这意味着它不会被序列化并转移到正在进行RMI调用的客户端。可能吗?

回答

2

也许吧。

可能绝对标记accountService领域为瞬态,这的确会被序列化并通过RMI发送(或者更准确地说,未能是序列化和抛出异常)停止它。但是,在这一点上,在另一侧重构的AccountRmiServiceImpl对于其accountService将具有空值,其在没有任何其他更改的情况下稍后肯定会导致NullPointerException

如果AccountServiceImpl不serialisable(Java中的),你仍然能够创建基于一些简单的serialisable信息的一个实例,那么你很幸运。您可以使用writeObject/readObject或writeReplace/readResolve方法自己实现序列化(有关详细信息,请参阅Serializable)。

如果AccountServiceImpl的实例在单词的任何意义上都不是可串行化的(例如,具有内联逻辑的匿名内部类以及对其外部范围中的最终局部变量的引用),则无法将其发送。对方会重新创建什么样的对象?如果出现这种情况,您需要重构代码以使类可以序列化。

+0

感谢您的答案dtsazza。假设AccountServiceImpl确实实现了Serializable。同样的问题重新出现,但现在使用DAO对象引用。 DAO实现不是可序列化的,因为Spring将它们注入为依赖关系,所以实现这个接口是没有意义的。 – 2009-11-16 16:00:47

+0

如果类的*内容*(即字段)不是可序列化的,则该类不是可序列化的。您需要采取“自下而上”的行动 - 如果您无法创建其中一个“Serializable”*和*无法手动重构的字段,那么您运气不好。不过,如果它们不是持久状态的一部分,则不要忘记将字段标记为“transient”(例如缓存或当前线程)。 – 2009-11-16 16:23:17

相关问题