Spring中存在大量的工具類,如:RMI相關的。Spring所提供的 RMI的支持大大簡化了RMI的開發難度,不過通常我們都是采用配置的方式,通過標準的spring bean來使用它們,這樣雖然簡化了開發,但是也限制了一些靈活性。因為bean的屬性都是在配置時設定的(如RMI客戶端中的服務的URL),而有時我 們需要在運行時生成這些屬性,這時其實只要我們直接使用這些工具類就可以了。
要在程序中直接使用RmiProxyFactoryBean,我們就必須了解spring是如何使用這個類為我們生成客戶端代理的,然后在程序中使用與spring相同的調用方式。
RmiProxyFactoryBean是一個工廠類,平時我們通過spring獲得的并不是這個工廠類的實例,而是用這個工廠類創建的proxy的實例,這個類實現了spring中標準的FactoryBean接口。FactoryBean接口中定義了三個方法:
| getObject() Return an instance (possibly shared or independent) of the object managed by this factory. |
| getObjectType() Return the type of object that this FactoryBean creates, or null if not known in advance. |
boolean | isSingleton() Is the bean managed by this factory a singleton or a prototype? |
我們通過getBean獲取這類工廠Bean(實現了FactoryBean接口的Bean)時,spring并不會返回工廠類的實例,而是調用工廠類的getObject方法并把方法的返回值返回給我們。
這樣你就明白了原來我們獲得的RMI的Proxy是通過RmiProxyFactoryBean的getObject方法生成的。
這時你一定認為下面的程序就可以搞定了:
…
RmiProxyFactoryBean proxy=new RmiProxyFactoryBean();
proxy.setServiceInterface(Calculator.class);
proxy.setServiceUrl(url);
Calculator client=(Calculator)proxy.getObject();
System.out.println(client.add(1,1));
…
運行程序你會發現上面這段程序并不成功,程序會拋出java.lang.NullPointerException異常。
問題在哪里呢?研究一下你會發現RmiProxyFactoryBean還實現了spring的
InitializingBean接口,接口中包含一個方法
afterPropertiesSet
()
,在所有屬性注入完成后spring會調用這個方法,因此上面的程序并沒有完全正確的模擬spring的調用過程。
修改代碼:
…
RmiProxyFactoryBean proxy=new RmiProxyFactoryBean();
proxy.setServiceInterface(Calculator.class);
proxy.setServiceUrl(url);
proxy.afterPropertiesSet();
Calculator client=(Calculator)proxy.getObject();
System.out.println(client.add(1,1));
…
這次終于成功了!
最后,此例告訴大家有時我們可以直接調用spring中的工具類,來完成我們的特殊需求,此時要注意的是正確模擬spring的對bean創建和調用過程。