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
|
我们通过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创建和调用过程。