根据我的印象,RmiProxyFactoryBean
应该生成类型为AccountService
的代理对象实例,该实例将注入accountService
实例的SimpleObject
属性中码。
我不明白为什么XML文件似乎指示Spring将RmiProxyFactoryBean
类型的对象注入accountService
对象实例的SimpleObject
属性?我期待XML文件中的显式指令告诉Spring如何从AccountService
实例获取RmiProxyFactoryBean
实例而不是注入RmiProxyFactoryBean
实例。我发现这令人困惑。
public class SimpleObject {
private AccountService accountService;
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
}
<bean class="example.SimpleObject">
<property name="accountService" ref="accountService"/>
</bean>
<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://HOST:1199/AccountService"/>
<property name="serviceInterface" value="example.AccountService"/>
</bean>
来源: http://static.springsource.org/spring/docs/2.5.x/reference/remoting.html (见17.2.2。)
由于
答案 0 :(得分:5)
因为Proxy Beans包装了有问题的对象,所以它们假装是被调用的接口(后来实际调用该接口)。
RmiProxyFactoryBean返回一个代理对象,这样当你的代码认为它正在你的example.AccountService类上调用一个方法时,它实际上是在一个bean上调用的,它具有与你的example.AccountService接口相同的接口:
<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
...
<property name="serviceInterface" value="example.AccountService"/>
</bean>
假设在接口上有一个名为example.AccountService.reconcile(Long amount)
的方法(仅为了示例)...
如果通常调用它,调用它的方法只会将其推入堆栈。但是如果example.AccountService对象是从上面的RmiProxyFactoryBean返回的,它将被包装在代理bean中。这个代理bean在其中有一个方法,它也被命名为reconcile
,并且参数为Long amount
,这使得它与它包装的原始example.AccountService
bean无法区分。这样,代理bean可以拥有它在实际example.AccountService.reconcile(Long amount)
方法中的代码之前,之后或代替它运行的代码。
代理bean来自一种完全不同的编程方式,称为面向方面编程(AOP),它处理交叉问题;即,似乎不符合正常OOP分离关注范围的代码。其中一些问题是例如事务划分,安全性和日志记录。
看起来您在上面手动执行此操作,但有时更容易使用SpringAOP在运行时编织它们,{{3}}具有用于选择代理bean并将其应用于现有代码的语言。
但是,请注意编程接口而不是编程到类。
答案 1 :(得分:2)
更简洁的方式是RmiProxyFactoryBean
实现FactoryBean
接口。实现该接口会指示Spring bean工厂本类是工厂本身,导致Spring在该类上调用getObject()
方法并将结果作为bean返回,而不是创建类本身的实例并返回。
所以,简短的回答,它是Spring的内置机制。